mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 10:31:46 +09:00
Merge tag 'android14-6.1.141_r00' into android14-6.1
This merges the android14-6.1.141_r00 tag into the android14-6.1 branch, catching it up with the latest LTS releases. It contains the following commits: *18282059e0Revert "espintcp: remove encap socket caching to avoid reference leak" *eb47017bf9Revert "genirq/msi: Store the IOMMU IOVA directly in msi_desc instead of iommu_cookie" *22d163151dRevert "perf: Avoid the read if the count is already updated" *f4b979262fRevert "coredump: hand a pidfd to the usermode coredump helper" *f23dc8c566Revert "ipv6: save dontfrag in cork" *b572d7f4f2Revert "serial: mctrl_gpio: split disable_ms into sync and no_sync APIs" *7f0c46ade6Revert "hrtimers: Force migrate away hrtimers queued after CPUHP_AP_HRTIMERS_DYING" *ef60b4555dMerge 6.1.141 into android14-6.1-lts |\ | *58485ff1a7Linux 6.1.141 | *0fadcc2043net: ethernet: ti: am65-cpsw: Lower random mac address error print to info | *12fd7e6a2cplatform/x86: thinkpad_acpi: Ignore battery threshold change event notification | *5d286f3cadplatform/x86: fujitsu-laptop: Support Lifebook S2110 hotkeys | *dcabad63e0NFS: Avoid flushing data while holding directory locks in nfs_rename() | *e1143267e9nvme-pci: add NVME_QUIRK_NO_DEEPEST_PS quirk for SOLIDIGM P44 Pro | *d8f13a8aefspi: spi-sun4i: fix early activation | *8f55d71b57um: let 'make clean' properly clean underlying SUBARCH as well | *fe4fb4134fplatform/x86: thinkpad_acpi: Support also NEC Lavie X1475JAS | *38e8c73f02nfs: don't share pNFS DS connections between net namespaces | *84b06a4293HID: quirks: Add ADATA XPG alpha wireless mouse support | *ac19091288coredump: hand a pidfd to the usermode coredump helper | *b2a5bf1cf4fork: use pidfd_prepare() | *1ced79b25fpid: add pidfd_prepare() | *fc7846a7d5coredump: fix error handling for replace_fd() | *3939280be9perf/arm-cmn: Initialise cmn->cpu earlier | *05b21a536aperf/arm-cmn: Fix REQ2/SNP2 mixup | *a0ec22fa20net_sched: hfsc: Address reentrant enqueue adding class to eltree twice | *a5a9c42cd7arm64: dts: qcom: sm8350: Fix typo in pil_camera_mem node | *0297e7ddf5af_unix: Fix uninit-value in __unix_walk_scc() | *c7edc6e616af_unix: Fix garbage collection of embryos carrying OOB with SCM_RIGHTS | *28201f38dcaf_unix: Add dead flag to struct scm_fp_list. | *f9977b176faf_unix: Don't access successor in unix_del_edges() during GC. | *951e454715af_unix: Try not to hold unix_gc_lock during accept(). | *61a75360dcaf_unix: Remove lock dance in unix_peek_fds(). | *5dfd283f46af_unix: Replace garbage collection algorithm. | *9734d332efaf_unix: Detect dead SCC. | *61f3d2706caf_unix: Assign a unique index to SCC. | *adfb68b39baf_unix: Avoid Tarjan's algorithm if unnecessary. | *b5b54a3875af_unix: Skip GC if no cycle exists. | *ccbe3d2acaaf_unix: Save O(n) setup of Tarjan's algo. | *edfa4872d0af_unix: Fix up unix_edge.successor for embryo socket. | *12365b707caf_unix: Save listener for embryo socket. | *a6c7ce40eaaf_unix: Detect Strongly Connected Components. | *878df6a069af_unix: Iterate all vertices by DFS. | *5593cb9b1caf_unix: Bulk update unix_tot_inflight/unix_inflight when queuing skb. | *f8194e511caf_unix: Link struct unix_edge when queuing skb. | *6b7a036eaaaf_unix: Allocate struct unix_edge for each inflight AF_UNIX fd. | *1002e86c46af_unix: Allocate struct unix_vertex for each inflight AF_UNIX fd. | *44aebf50faaf_unix: Remove CONFIG_UNIX_SCM. | *6afc128665af_unix: Remove io_uring code for GC. | *a1ee63f7a0af_unix: Replace BUG_ON() with WARN_ON_ONCE(). | *e9bd632f98af_unix: Try to run GC async. | *ceb8bd6c69af_unix: Run GC on only one CPU. | *7637a75aedaf_unix: Return struct unix_sock from unix_get_socket(). | *63d00b25e0af_unix: Kconfig: make CONFIG_UNIX bool | *36679fab54btrfs: check folio mapping after unlock in relocate_one_folio() | *82ac6adbbbhrtimers: Force migrate away hrtimers queued after CPUHP_AP_HRTIMERS_DYING | *22e3ccf1d5octeontx2-pf: Fix page pool frag allocation warning | *173d9d060cocteontx2-pf: Fix page pool cache index corruption. | *a84f95fecbocteontx2-pf: fix page_pool creation fail for rings > 32k | *bc952bf4e0dmaengine: idxd: Fix passing freed memory in idxd_cdev_open() | *50026aa530x86/mm/init: Handle the special case of device private pages in add_pages(), to not increase max_pfn and trigger dma_addressing_limited() bounce buffers bounce buffers | *bb6e80472ei3c: master: svc: Fix implicit fallthrough in svc_i3c_master_ibi_work() | *79c9df2d7apinctrl: tegra: Fix off by one in tegra_pinctrl_get_group() | *c0c0b03ea1serial: sh-sci: Save and restore more registers | *9502ebf2d2kbuild: Disable -Wdefault-const-init-unsafe | *2c29113154spi: spi-fsl-dspi: Reset SR flags before sending a new message | *8bdaffcdd7spi: spi-fsl-dspi: Halt the module after a new message transfer | *f48dc6849cspi: spi-fsl-dspi: restrict register range for regmap access | *795cea4731ksmbd: fix stream write failure | *4c8d922337Revert "arm64: dts: allwinner: h6: Use RSB for AXP805 PMIC connection" | *b9f7969173mm/page_alloc.c: avoid infinite retries caused by cpuset race | *460664bf8bmemcg: always call cond_resched() after fn() | *9c40d1f7b7Revert "drm/amd: Keep display off while going into S4" | *080da7b2fcsmb: client: Reset all search buffer pointers when releasing buffer | *c8623231e0smb: client: Fix use-after-free in cifs_fill_dirent | *34e2f19e0edrm/edid: fixed the bug that hdr metadata was not reset | *60bd13f8c4platform/x86: dell-wmi-sysman: Avoid buffer overflow in current_password_store() | *836024a6c8llc: fix data loss when reading from a socket in llc_ui_recvmsg() | *eefcc081acALSA: hda/realtek: Add quirk for Lenovo Yoga Pro 7 14ASP10 | *f3e14d706eALSA: pcm: Fix race of buffer access at PCM OSS layer | *6d7d458c41can: bcm: add missing rcu read protection for procfs content | *2a437b86accan: bcm: add locking for bcm_op runtime updates | *24ee050bb9can: slcan: allow reception of short error messages | *cceb15864epadata: do not leak refcount in reorder_work | *f0f3d09f53crypto: algif_hash - fix double free in hash_accept | *3cb003b959octeontx2-af: Fix APR entry mapping based on APR_LMT_CFG | *7b1357a108octeontx2-af: Set LMT_ENA bit for APR table entries | *b8fcae6d2enet/tipc: fix slab-use-after-free Read in tipc_aead_encrypt_done | *a005991013octeontx2-pf: Add AF_XDP non-zero copy support | *2a2d7bf86docteontx2-pf: Add support for page pool | *f1dde3eb17sch_hfsc: Fix qlen accounting bug when using peek in hfsc_enqueue() | *f2138e462cio_uring: fix overflow resched cqe reordering | *8620be38cfnet: lan743x: Restore SGMII CTRL register on resume | *e8138b81d3net: dwmac-sun8i: Use parsed internal PHY address instead of 1 | *b6556470bbice: fix vf->num_mac count with port representors | *2cee71a1a2bridge: netfilter: Fix forwarding of fragmented packets | *15efa7d00fBluetooth: L2CAP: Fix not checking l2cap_chan security level | *7549955105dmaengine: idxd: Fix ->poll() return value | *35e6a84883xfrm: Sanitize marks before insert | *c4bfea4b61clk: sunxi-ng: d1: Add missing divider for MMC mod clocks | *8509fb9decremoteproc: qcom_wcnss: Fix on platforms without fallback regulators | *d19d0157eddmaengine: idxd: Fix allowing write() from different address spaces | *206d8a7b8cdmaengine: idxd: add idxd_copy_cr() to copy user completion record during page fault handling | *22d907d735dmaengine: idxd: add per DSA wq workqueue for processing cr faults | *e4cde54b46espintcp: remove encap socket caching to avoid reference leak | *9b0915e72b__legitimize_mnt(): check for MNT_SYNC_UMOUNT should be under mount_lock | *a58442f75bxenbus: Allow PVH dom0 a non-local xenstore | *390940c7f3wifi: iwlwifi: add support for Killer on MTL | *0528bba48dbtrfs: correct the order of prelim_ref arguments in btrfs__prelim_ref | *7c0394dbbdio_uring/fdinfo: annotate racy sq/cq head/tail reads | *c240375587nvmet-tcp: don't restore null sk_state_change | *e104460e8aALSA: hda/realtek: Add quirk for HP Spectre x360 15-df1xxx | *9fce40ac35ASoC: Intel: bytcr_rt5640: Add DMI quirk for Acer Aspire SW3-013 | *181438633apinctrl: meson: define the pull up/down resistor value as 60 kOhm | *f4ae54bffbASoC: imx-card: Adjust over allocation of memory in imx_card_parse_of() | *ffb55ddf26drm: Add valid clones check | *d822a8e3fbdrm/panel-edp: Add Starry 116KHD024006 | *6a93438018drm/atomic: clarify the rules around drm_atomic_state->allow_modeset | *a78b779206wifi: ath9k: return by of_get_mac_address | *f60d34d4a4regulator: ad5398: Add device tree support | *d97d423ad1spi: zynqmp-gqspi: Always acknowledge interrupts | *8d0c67acdfwifi: rtw89: add wiphy_lock() to work that isn't held wiphy_lock() yet | *f4c4d18f72wifi: rtw88: Don't use static local variable in rtw8822b_set_tx_power_index_by_rate | *60f09a491fwifi: rtl8xxxu: retry firmware download on error | *e7e61e09ceperf/amd/ibs: Fix perf_ibs_op.cnt_mask for CurCnt | *77a7df4b23bpftool: Fix readlink usage in get_fd_type | *658a933038drm/ast: Find VBIOS mode from regular display size | *762535bc37ASoC: codecs: pcm3168a: Allow for 24-bit in provider mode | *08aec29a16HID: usbkbd: Fix the bit shift number for LED_KANA | *3b72b12487scsi: st: Restore some drive settings after reset | *9f9a65de83scsi: lpfc: Free phba irq in lpfc_sli4_enable_msi() when pci_irq_vector() fails | *14f8b37e1cscsi: lpfc: Handle duplicate D_IDs in ndlp search-by D_ID routine | *31fbeed785net/mana: fix warning in the writer of client oob | *e0d0424a8aice: count combined queues using Rx/Tx count | *e1c3bfe365perf: Avoid the read if the count is already updated | *84916c757crcu: fix header guard for rcu_all_qs() | *e2df1936c1rcu: handle unstable rdp in rcu_read_unlock_strict() | *6090e60428rcu: handle quiescent states for PREEMPT_RCU=n, PREEMPT_COUNT=y | *77835a04b1r8169: don't scan PHY addresses > 0 | *784b78295avxlan: Annotate FDB data races | *73b9240149media: qcom: camss: csid: Only add TPG v4l2 ctrl if TPG hardware is available | *50b7e3276bhwmon: (xgene-hwmon) use appropriate type for the latency value | *e35875dd2bclk: qcom: camcc-sm8250: Use clk_rcg2_shared_ops for some RCGs | *5338343080wifi: rtw88: Fix download_firmware_validate() for RTL8814AU | *83b5df3df8r8152: add vendor/device ID pair for Dell Alienware AW1022z | *ce534438a8ip: fib_rules: Fetch net from fib_rule in fib[46]_rule_configure(). | *81d2a85c65arch/powerpc/perf: Check the instruction type before creating sample with perf_mem_data_src | *6dc0a704f5wifi: mac80211: remove misplaced drv_mgd_complete_tx() call | *9fc9237ffawifi: mac80211: don't unconditionally call drv_mgd_complete_tx() | *5d2af99518net/mlx5e: reduce rep rxq depth to 256 for ECPF | *468255c8ednet/mlx5e: set the tx_queue_len for pfifo_fast | *d525e62f18net/mlx5: Extend Ethtool loopback selftest to support non-linear SKB | *e4f6a56f45drm/amd/display/dm: drop hw_support check in amdgpu_dm_i2c_xfer() | *9131a4be79drm/amdgpu: enlarge the VBIOS binary size limit | *bc40b6248adrm/amd/display: Initial psr_version with correct setting | *81f4b82cf3drm/amdgpu: reset psp->cmd to NULL after releasing the buffer | *cfdf164ef5phy: core: don't require set_mode() callback for phy_get_mode() to work | *b6e568caafserial: sh-sci: Update the suspend/resume support | *5e3ee618d6clk: qcom: clk-alpha-pll: Do not use random stack value for recalc rate | *a6e871c912net/mlx4_core: Avoid impossible mlx4_db_alloc() order value | *0d52c6168dkunit: tool: Use qboot on QEMU x86_64 | *5d08c89c2asmack: recognize ipv4 CIPSO w/o categories | *b23976c6f9pinctrl: devicetree: do not goto err when probing hogs in pinctrl_dt_to_map | *709b1fb223ASoC: soc-dai: check return value at snd_soc_dai_set_tdm_slot() | *4ffaac5e21ASoC: tas2764: Power up/down amp on mute ops | *ec3a91e22bASoC: tas2764: Mark SW_RESET as volatile | *051f0ee928ASoC: tas2764: Add reg defaults for TAS2764_INT_CLK_CFG | *d9f7ac25ffASoC: ops: Enforce platform maximum on initial value | *963bac7f04net/mlx5: Apply rate-limiting to high temperature warning | *89acf46b9enet/mlx5: Modify LSB bitmask in temperature event to include only the first bit | *4d142115a9media: test-drivers: vivid: don't call schedule in loop | *79dbd04fccvxlan: Join / leave MC group after remote changes | *23ecfd5383ACPI: HED: Always initialize before evged | *58fe8fead9PCI: Fix old_size lower bound in calculate_iosize() too | *5f1ecc9aa5eth: mlx4: don't try to complete XDP frames in netpoll | *0d9d54113fcan: c_can: Use of_property_present() to test existence of DT property | *e3c93c7917pmdomain: imx: gpcv2: use proper helper for property detection | *24eb0979ffRDMA/core: Fix best page size finding when it can cross SG entries | *68435c1fa3serial: mctrl_gpio: split disable_ms into sync and no_sync APIs | *74db6edb69i3c: master: svc: Flush FIFO before sending Dynamic Address Assignment(DAA) | *07bf524a78EDAC/ie31200: work around false positive build warning | *ef1158a6a6net: pktgen: fix access outside of user given buffer in pktgen_thread_write() | *70a9888018wifi: rtw89: fw: propagate error code from rtw89_h2c_tx() | *3635589fa5wifi: rtw88: Fix rtw_desc_to_mcsrate() to handle MCS16-31 | *1c17d07fc4wifi: rtw88: Fix rtw_init_ht_cap() for RTL8814AU | *100c6e2d0cwifi: rtw88: Fix rtw_init_vht_cap() for RTL8814AU | *526ec91398scsi: mpt3sas: Send a diag reset if target reset fails | *790f74d684clocksource: mips-gic-timer: Enable counter when CPUs start | *3972bd4ca5MIPS: pm-cps: Use per-CPU variables as per-CPU, not per-core | *e4d3763223genirq/msi: Store the IOMMU IOVA directly in msi_desc instead of iommu_cookie | *3394aafdc8MIPS: Use arch specific syscall name match function | *ea4497337fx86/kaslr: Reduce KASLR entropy on most x86 systems | *95d0892433dm: fix unconditional IO throttle caused by REQ_PREFLUSH | *75b01247b4libbpf: Fix out-of-bound read | *01b4545bbcmedia: adv7180: Disable test-pattern control on adv7180 | *a9edb70084cpuidle: menu: Avoid discarding useful information | *60750801cax86/nmi: Add an emergency handler in nmi_desc & use it in nmi_shootdown_cpus() | *42733703c4drm/amd/display: handle max_downscale_src_width fail check | *a66f46751cx86/build: Fix broken copy command in genimage.sh when making isoimage | *5f496a9f1csoc: ti: k3-socinfo: Do not use syscon helper to build regmap | *3572663c55bonding: report duplicate MAC address in all situations | *365e617487net: xgene-v2: remove incorrect ACPI_PTR annotation | *62e7868f06net: ethernet: mtk_ppe_offload: Allow QinQ, double ETH_P_8021Q only | *2272c9d14cleds: pwm-multicolor: Add check for fwnode_property_read_u32 | *c8cc14eeb2drm/amdkfd: KFD release_work possible circular locking | *1964a698cbselftests/net: have `gro.sh -t` return a correct exit code | *866ae3322fnet/mlx5: Avoid report two health errors on same syndrome | *c6aa1d6bd6firmware: arm_ffa: Set dma_mask for ffa devices | *de963561efPCI: brcmstb: Add a softdep to MIP MSI-X driver | *9fe2a6513aPCI: brcmstb: Expand inbound window size up to 64GB | *2d533b62dbsoc: apple: rtkit: Implement OSLog buffers properly | *8d64b2aa3esoc: apple: rtkit: Use high prio work queue | *0c14267f4dfpga: altera-cvp: Increase credit timeout | *31b96c1543drm/mediatek: mtk_dpi: Add checks for reg_h_fre_con existence | *eeb808ce1eARM: at91: pm: fix at91_suspend_finish for ZQ calibration | *05315e1507hwmon: (gpio-fan) Add missing mutex locks | *594dbf0a19x86/bugs: Make spectre user default depend on MITIGATION_SPECTRE_V2 | *a5df17f35bclk: imx8mp: inform CCF of maximum frequency of clocks | *6782a62c32media: uvcvideo: Add sanity check to uvc_ioctl_xu_ctrl_map | *7d49558be0drm/rockchip: vop2: Add uv swap for cluster window | *79f3edb937ipv4: fib: Move fib_valid_key_len() to rtm_to_fib_config(). | *f29dd5afa1ALSA: hda/realtek: Enable PC beep passthrough for HP EliteBook 855 G7 | *628ff556e4perf/hw_breakpoint: Return EOPNOTSUPP for unsupported breakpoint type | *48bd9b9d66net: pktgen: fix mpls maximum labels list parsing | *d1f95fbdf6net: ethernet: ti: cpsw_new: populate netdev of_node | *4473bd0993pinctrl: bcm281xx: Use "unsigned int" instead of bare "unsigned" | *9d1a5be86dmedia: cx231xx: set device_caps for 417 | *41f654291bdrm/amdgpu: Do not program AGP BAR regs under SRIOV in gfxhub_v1_0.c | *8d0d4c11caremoteproc: qcom_wcnss: Handle platforms with only single power domain | *fdf85aa795net: phylink: use pl->link_interface in phylink_expects_phy() | *15602508adorangefs: Do not truncate file size | *00586b78eedm cache: prevent BUG_ON by blocking retries on failed device resumes | *2996d38f2dmedia: c8sectpfe: Call of_node_put(i2c_bus) only once in c8sectpfe_probe() | *b649481a1cARM: tegra: Switch DSI-B clock parent to PLLD on Tegra114 | *fd10aa99efieee802154: ca8210: Use proper setters and getters for bitwise types | *9569e35890rtc: ds1307: stop disabling alarms on probe | *2c86fafda7tcp: bring back NUMA dispersion in inet_ehash_locks_alloc() | *e6ca4d234bALSA: seq: Improve data consistency at polling | *aba0c50463powerpc/prom_init: Fixup missing #size-cells on PowerBook6,7 | *806d3ee930arm64: tegra: p2597: Fix gpio for vdd-1v8-dis regulator | *a98bd864e1crypto: lzo - Fix compression buffer overrun | *8917266622cpufreq: tegra186: Share policy per cluster | *239afef07eiommu/amd/pgtbl_v2: Improve error handling | *64e88f718eASoC: qcom: sm8250: explicitly set format in sm8250_be_hw_params_fixup() | *f306821a7bauxdisplay: charlcd: Partially revert "Move hwidth and bwidth to struct hd44780_common" | *9e5228610fgfs2: Check for empty queue in run_queue | *0b60d03644drm/amd/display: calculate the remain segments for all pipes | *4f809be95dipv6: save dontfrag in cork | *4a8fcd77cehwmon: (dell-smm) Increment the number of fans | *d0306f88b4mmc: sdhci: Disable SD card clock before changing parameters | *03c9ac48aemmc: dw_mmc: add exynos7870 DW MMC support | *5cdb89f76earm64/mm: Check PUD_TYPE_TABLE in pud_bad() | *3bb62cc313netfilter: conntrack: Bound nf_conntrack sysctl writes | *e563401934timer_list: Don't use %pK through printk() | *209f290b4fposix-timers: Add cond_resched() to posix_timer_add() search loop | *8d67953978RDMA/uverbs: Propagate errors from rdma_lookup_get_uobject() | *6944537397ext4: reject the 'data_err=abort' option in nojournal mode | *e472c3d8adASoC: sun4i-codec: support hp-det-gpios property | *7fcfed72a5pinctrl-tegra: Restore SFSEL bit when freeing pins | *02d850de94xen: Add support for XenServer 6.1 platform device | *9af7628ee6net/smc: use the correct ndev to find pnetid by pnetid table | *6d974bd692dm: restrict dm device size to 2^63-512 bytes | *3b5cc6e49ccrypto: octeontx2 - suppress auth failure screaming due to negative tests | *df5a4416c0kbuild: fix argument parsing in scripts/config | *e78a34da61ASoC: mediatek: mt6359: Add stub for mt6359_accdet_enable_jack_detect | *669a53eeccthunderbolt: Do not add non-active NVM if NVM upgrade is disabled for retimer | *7d9682b015rtc: rv3032: fix EERD location | *9ff6d39f17tcp: reorganize tcp_in_ack_event() and tcp_count_delivered() | *a73f1ba994bpf: Return prog btf_id without capable check | *6cd9c9167cvfio/pci: Handle INTx IRQ_NOTCONNECTED | *4c92971bedscsi: st: ERASE does not change tape location | *1f20b8eccfscsi: st: Tighten the page format heuristics with MODE SELECT | *7f778cbffeext4: reorder capability check last | *ea4d9e1a6cum: Update min_low_pfn to match changes in uml_reserved | *f8ddfaab46um: Store full CSGSFS and SS register from mcontext | *75f74c89a8dlm: make tcp still work in multi-link env | *f2985a1de6i3c: master: svc: Fix missing STOP for master request | *227c253c9edrm/amd/display: Guard against setting dispclk low for dcn31x | *822c0e09f4btrfs: send: return -ENAMETOOLONG when attempting a path that is too long | *22bb11b3d5btrfs: get zone unusable bytes while holding lock at btrfs_reclaim_bgs_work() | *e2965d9d21btrfs: fix non-empty delayed iputs list on unmount due to async workers | *013614c23ebtrfs: run btrfs_error_commit_super() early | *2abb4bb795btrfs: avoid linker error in btrfs_find_create_tree_block() | *df4af023f6btrfs: make btrfs_discard_workfn() block_group ref explicit | *e212c8e9f2i2c: pxa: fix call balance of i2c->clk handling routines | *fb6a04c3b7i2c: qup: Vote for interconnect bandwidth to DRAM | *8c18c904d3x86/mm: Check return value from memblock_phys_alloc_range() | *fa73abd359mmc: host: Wait for Vdd to settle on card power off | *db1aef51b8libnvdimm/labels: Fix divide error in nd_label_data_init() | *1671494b71PCI: vmd: Disable MSI remapping bypass under Xen | *5ad8142667pNFS/flexfiles: Report ENETDOWN as a connection error | *1d5786b3batools/build: Don't pass test log files to linker | *1325473abaPCI: dwc: ep: Ensure proper iteration over outbound map windows | *1fdd7255d5objtool: Properly disable uaccess validation | *2896063907lockdep: Fix wait context check on softirq for PREEMPT_RT | *2d905fdb7fdql: Fix dql->limit value when reset. | *33aaf2e4d3thermal/drivers/qoriq: Power down TMU on system suspend | *61ce7181fbSUNRPC: rpcbind should never reset the port to the value '0' | *18dd5c41f6SUNRPC: rpc_clnt_set_transport() must not change the autobind setting | *b11ffd1dc3NFSv4: Treat ENETUNREACH errors as fatal for state recovery | *8e93857d8dcifs: Fix establishing NetBIOS session for SMB2+ connection | *96106d4f3ffbdev: core: tileblit: Implement missing margin clearing for tileblit | *57aa1e8197fbcon: Use correct erase colour for clearing in fbcon | *af6e4ccb08fbdev: fsl-diu-fb: add missing device_remove_file() | *d8aea4921fmailbox: use error ret code of of_parse_phandle_with_args() | *6707f9749dtracing: Mark binary printing functions with __printf() attribute | *cdfe09355carm64: Add support for HIP09 Spectre-BHB mitigation | *0b99bcbd62SUNRPC: Don't allow waiting for exiting tasks | *2bd25a7916NFS: Don't allow waiting for exiting tasks | *429d487d94NFSv4: Check for delegation validity in nfs_start_delegation_return_locked() | *f706cb4e37fuse: Return EPERM rather than ENOSYS from link() | *b413cf7ff5cifs: Fix negotiate retry functionality | *5d736eee3ccifs: Fix querying and creating MF symlinks over SMB1 | *17e53a15e6cifs: Add fallback for SMB2 CREATE without FILE_READ_ATTRIBUTES | *8696f0e4f6s390/vfio-ap: Fix no AP queue sharing allowed message written to kernel log | *53dd81d7bakconfig: merge_config: use an empty file as initfile | *aa8687470asamples/bpf: Fix compilation failure for samples/bpf on LoongArch Fedora | *0953353269bpf: fix possible endless loop in BPF map iteration | *5f3d693861selftests/bpf: Mitigate sockmap_ktls disconnect_after_delete failure | *f238c9c15ddrm/amdgpu: Allow P2P access through XGMI | *4964646234net: enetc: refactor bulk flipping of RX buffers to separate function | *1d44f1511bscsi: mpi3mr: Add level check to control event logging | *91fe35809ecgroup: Fix compilation issue due to cgroup_mutex not being exported | *04aa1f6d16dma-mapping: avoid potential unused data compilation warning | *b6d6419548virtio_ring: Fix data race by tagging event_triggered as racy for KCSAN | *6815846e0cscsi: target: iscsi: Fix timeout on deleted connection | *ee963a9847phy: renesas: rcar-gen3-usb2: Assert PLL reset on PHY power off | *a640e906d9phy: renesas: rcar-gen3-usb2: Lock around hardware registers and driver data | *6dbb6f00dcphy: renesas: rcar-gen3-usb2: Move IRQ request in probe | *ba7694f61cphy: renesas: rcar-gen3-usb2: Add support to initialize the bus | *262e32568agpio: pca953x: fix IRQ storm on system wake up | *aa34c055d3gpio: pca953x: Simplify code with cleanup helpers | *af7488d114gpio: pca953x: Split pca953x_restore_context() and pca953x_save_context() | *59047be46cgpio: pca953x: Add missing header(s) * |deadfd1486Merge android14-6.1 into android14-6.1-lts * |f4843e14bfMerge 6.1.140 into android14-6.1-lts |\| | *da3c5173c5Linux 6.1.140 | *05e85d3767x86/modules: Set VM_FLUSH_RESET_PERMS in module_alloc() | *4e6310e8d4drm/amdgpu: fix pm notifier handling | *2c914aac95spi: cadence-qspi: fix pointer reference in runtime PM hooks | *55bf541e01ipv4: Fix uninit-value access in __ip_make_skb() | *a05c1ede50ipv6: Fix potential uninit-value access in __ip6_make_skb() | *b7fd784d7cbnxt_en: Fix receive ring space parameters when XDP is active | *ab47d72b73platform/x86/amd/pmc: Only disable IRQ1 wakeup where i8042 actually enabled it | *f6421555dbarm64/sme: Always exit sme_alloc() early with existing storage | *b0f013bebfnetfilter: nf_tables: do not defer rule destruction via call_rcu | *e6c32a64d6netfilter: nf_tables: wait for rcu grace period on net_device removal | *bbd68196acnetfilter: nf_tables: pass nft_chain to destroy function, not nft_ctx | *18eb53a273btrfs: don't BUG_ON() when 0 reference count at btrfs_lookup_extent_info() | *386507cb6fsctp: add mutual exclusion in proc_sctp_do_udp_port() | *3926b572fdhwpoison, memory_hotplug: lock folio before unmap hwpoisoned folio | *091a7f20d5LoongArch: Explicitly specify code model in Makefile | *9e80f366ebbpf, arm64: Fix address emission with tag-based KASAN enabled | *0771494784bpf, arm64: Fix trampoline for BPF_TRAMP_F_CALL_ORIG | *92f08673d3riscv: mm: Fix the out of bound issue of vmemmap address | *e5ec1c24e7mm/vmscan: fix a bug calling wakeup_kswapd() with a wrong zone index | *09b18c2435selftests/mm: compaction_test: support platform with huge mount of memory | *0529646acdusb: typec: fix pm usage counter imbalance in ucsi_ccg_sync_control() | *e44189455cusb: typec: fix potential array underflow in ucsi_ccg_sync_control() | *f1c5ddaef5usb: typec: altmodes/displayport: create sysfs nodes as driver's default device attribute group | *f32451ca4cusb: typec: ucsi: displayport: Fix deadlock | *d8ef6140fedmaengine: idxd: fix memory leak in error handling path of idxd_pci_probe | *64afd9a1f6dmaengine: idxd: fix memory leak in error handling path of idxd_alloc | *68ac5a01f6dmaengine: idxd: Add missing idxd cleanup to fix memory leak in remove call | *24d9c14fdcdmaengine: idxd: Add missing cleanups in cleanup internals | *9b4947544bdmaengine: idxd: Add missing cleanup for early error out in idxd_setup_internals | *50f2300178dmaengine: idxd: fix memory leak in error handling path of idxd_setup_groups | *11fd63ea08dmaengine: idxd: fix memory leak in error handling path of idxd_setup_engines | *d584acdf54dmaengine: idxd: fix memory leak in error handling path of idxd_setup_wqs | *c70ec7dc88dmaengine: ti: k3-udma: Use cap_mask directly from dma_device structure instead of a local copy | *df5987e76admaengine: ti: k3-udma: Add missing locking | *8e460b77b7net: qede: Initialize qede_ll_ops with designated initializer | *b892e830d1wifi: mt76: disable napi on driver removal | *e424894340smb: client: fix memory leak during error handling for POSIX mkdir | *d5b4310993scsi: sd_zbc: block: Respect bio vector limits for REPORT ZONES buffer | *4861b3d2a4phy: renesas: rcar-gen3-usb2: Set timing registers only once | *9b85a453eaphy: renesas: rcar-gen3-usb2: Fix role detection on unbind/bind | *f774628bc1phy: Fix error handling in tegra_xusb_port_init | *12ba469abetracing: samples: Initialize trace_array_printk() with the correct function | *cbe20c2c83ftrace: Fix preemption accounting for stacktrace filter command | *c4edc834d2ftrace: Fix preemption accounting for stacktrace trigger command | *763db1b8b0Drivers: hv: vmbus: Remove vmbus_sendpacket_pagebuffer() | *6ef4c72213Drivers: hv: Allow vmbus_sendpacket_mpb_desc() to create multiple ranges | *b47a984fafhv_netvsc: Remove rmsg_pgcnt | *86b05e14c4hv_netvsc: Preserve contiguous PFN grouping in the page buffer array | *3e5210def3hv_netvsc: Use vmbus_sendpacket_mpb_desc() to send VMBus messages | *3becc659f9dma-buf: insert memory barrier before updating num_fences | *01dfc57326ALSA: usb-audio: Add sample rate quirk for Microdia JP001 USB Camera | *7ba07e109fALSA: usb-audio: Add sample rate quirk for Audioengine D1 | *f5abc1344fALSA: es1968: Add error handling for snd_pcm_hw_constraint_pow2() | *b71a04bae2ACPI: PPTT: Fix processor subtable walk | *0638bad18ddrm/amd/display: Avoid flooding unnecessary info messages | *d9632f4aaedrm/amd/display: Correct the reply value when AUX write incomplete | *0f035835b4btrfs: fix discard worker infinite loop after disabling discard | *0567e7951fLoongArch: Fix MAX_REG_OFFSET calculation | *02a11d8638dmaengine: Revert "dmaengine: dmatest: Fix dmatest waiting less when interrupted" | *8f2eb3adb3NFSv4/pnfs: Reset the layout state after a layoutreturn | *8f7f96549bnet/tls: fix kernel panic when alloc_page failed | *2c09d6460focteontx2-pf: macsec: Fix incorrect max transmit size in TX secy | *6ba30f7aa2regulator: max20086: fix invalid memory access | *10ea81e478qlcnic: fix memory leak in qlcnic_sriov_channel_cfg_cmd() | *1e577aeb51net/mlx5e: Disable MACsec offload for uplink representor profile | *6fbcfa3691ALSA: sh: SND_AICA should depend on SH_DMA_API | *9609469159nvme-pci: acquire cq_poll_lock in nvme_poll_irqdisable | *6fc167d45fnvme-pci: make nvme_pci_npages_prp() __always_inline | *4626234ca3net: dsa: sja1105: discard incoming frames in BR_STATE_LISTENING | *aace6b6389net: cadence: macb: Fix a possible deadlock in macb_halt_tx. | *1cb9a891cfnet: mctp: Ensure keys maintain only one ref to corresponding dev | *d38939ebe0net_sched: Flush gso_skb list too during ->change() | *915c3de392spi: loopback-test: Do not split 1024-byte hexdumps | *85fb7f8ca5nfs: handle failure of nfs_get_lock_context in unlock path | *01b76cc8caHID: uclogic: Add NULL check in uclogic_input_configured() | *de9b6d0635HID: thrustmaster: fix memory leak in thrustmaster_interrupts() | *52daccfc3fRDMA/rxe: Fix slab-use-after-free Read in rxe_queue_cleanup bug | *718df14948clocksource/i8253: Use raw_spinlock_irqsave() in clockevent_i8253_disable() | *c4a550e0baiio: chemical: sps30: use aligned_s64 for timestamp | *39d30f8ecciio: adc: ad7768-1: Fix insufficient alignment of timestamp. | *ced7c789e3Revert "drm/amd: Stop evicting resources on APUs in suspend" | *a2419fa7fedrm/amd: Add Suspend/Hibernate notification callback support | *43b8b33b81drm/amdgpu: trigger flr_work if reading pf2vf data failed | *c3408b49e3drm/amdgpu: Fix the runtime resume failure issue | *6b9418c825drm/amd: Stop evicting resources on APUs in suspend | *d7b0db1246iio: adc: ad7266: Fix potential timestamp alignment issue. | *22bed5bd0dtpm: tis: Double the timeout B to 4s | *2f81039276tracing: probes: Fix a possible race in trace_probe_log APIs | *5eadacf806platform/x86: asus-wmi: Fix wlan_ctrl_by_user detection | *44f3f92053binfmt_elf: Move brk for static PIE even if ASLR disabled | *af66f1d950binfmt_elf: Honor PT_LOAD alignment for static PIE | *2fb38e1a01binfmt_elf: Calculate total_size earlier | *add3a49ae9selftests/exec: Build both static and non-static load_address tests | *7a60eba05abinfmt_elf: Leave a gap between .bss and brk | *fea22a3e06selftests/exec: load_address: conform test to TAP format output | *1707053766binfmt_elf: elf_bss no longer used by load_elf_binary() | *86811e8778binfmt_elf: Support segments with 0 filesz and misaligned starts | *e20878d4ebbinfmt: Fix whitespace issues * |d2136f8626Merge 6.1.139 into android14-6.1-lts |/ *325285d9fcLinux 6.1.139 *69afd82670x86/its: FineIBT-paranoid vs ITS *73c71762fex86/alternatives: Remove faulty optimization *7e00c01ff8x86/alternative: Optimize returns patching *c2bece04bax86/its: Fix build errors when CONFIG_MODULES=n *959cadf09dx86/its: Use dynamic thunks for indirect branches *9502e83c22x86/ibt: Keep IBT disabled during alternative patching *e6da4a83e3x86/its: Align RETs in BHB clear sequence to avoid thunking *139c0b8318x86/its: Add "vmexit" option to skip mitigation on some CPUs *b1701fee52x86/its: Enable Indirect Target Selection mitigation *dbd8f170afx86/its: Add support for ITS-safe return thunk *5e7d4f2acex86/its: Add support for ITS-safe indirect thunk *0eda20c29ex86/its: Enumerate Indirect Target Selection (ITS) bug *ed2e894a76Documentation: x86/bugs/its: Add ITS documentation *b1ef84b0ffx86/speculation: Remove the extra #ifdef around CALL_NOSPEC *fb3768004ex86/speculation: Add a conditional CS prefix to CALL_NOSPEC *4bc1033dffx86/speculation: Simplify and make CALL_NOSPEC consistent *db734ba733x86/bhi: Do not set BHI_DIS_S in 32-bit mode *cebc238b02x86/bpf: Add IBHF call at end of classic BPF *845c707b80x86/bpf: Call branch history clearing sequence on exit *9fc1391552arm64: proton-pack: Add new CPUs 'k' values for branch mitigation *6e52d043f7arm64: bpf: Only mitigate cBPF programs loaded by unprivileged users *8fe5c37b0earm64: bpf: Add BHB mitigation to the epilogue for cBPF programs *4977712341arm64: proton-pack: Expose whether the branchy loop k value *351a505eb4arm64: proton-pack: Expose whether the platform is mitigated by firmware *cc0b8e148carm64: insn: Add support for encoding DSB *361dfa7f5cRevert "net: phy: microchip: force IRQ polling mode for lan88xx" *b82c386898io_uring: ensure deferred completions are posted for multishot *95b9acb0bbio_uring: always arm linked timeouts prior to issue *0e42a14899do_umount(): add missing barrier before refcount checks in sync case *8642cbf11envme: unblock ctrl state transition for firmware update *bd68de433fdrm/panel: simple: Update timings for AUO G101EVN010 *d189b461d5MIPS: Fix MAX_REG_OFFSET *ea25ee0bb4iio: adc: dln2: Use aligned_s64 for timestamp *b6c984f4ebiio: accel: adxl355: Make timestamp 64-bit aligned using aligned_s64 *8f0064eb22types: Complement the aligned types with signed 64-bit one *35061dc5f6iio: temp: maxim-thermocouple: Fix potential lack of DMA safe buffer. *6f371b751biio: accel: adxl367: fix setting odr for activity time update *7591a2e6c0usb: usbtmc: Fix erroneous generic_read ioctl return *5f72912d35usb: usbtmc: Fix erroneous wait_srq ioctl return *a647d960fbusb: usbtmc: Fix erroneous get_stb ioctl error returns *1956c3d878USB: usbtmc: use interruptible sleep in usbtmc_read *076ab0631eusb: typec: ucsi: displayport: Fix NULL pointer access *2e89025609usb: typec: tcpm: delay SNK_TRY_WAIT_DEBOUNCE to SRC_TRYWAIT transition *7d6224d1cfusb: host: tegra: Prevent host controller crash when OTG port is used *6fe2677bcfusb: gadget: tegra-xudc: ACK ST_RC after clearing CTRL_RUN *ee51a5d322usb: cdnsp: fix L1 resume issue for RTL_REVISION_NEW_LPM version *0554dade57usb: cdnsp: Fix issue with resuming from L1 *4c3a0b0b23ocfs2: stop quota recovery before disabling quotas *6e5c3d9f29ocfs2: implement handshaking with ocfs2 recovery thread *c77a473d6eocfs2: switch osb->disable_recovery to enum *9e7b49ce4fmodule: ensure that kobject_put() is safe for module type kobjects *8b02f85e84xenbus: Use kref to track req lifetime *cf61669c50usb: uhci-platform: Make the clock really optional *b04cfc229adrm/amdgpu/hdp5.2: use memcfg register to post the write for HDP flush *470f56fc35drm/amd/display: Copy AUX read reply data whenever length > 0 *9e83c84de3drm/amd/display: Fix wrong handling for AUX_DEFER case *2cca631283drm/amd/display: Remove incorrect checking in dmub aux handler *f3385a056adrm/amd/display: Fix the checking condition in dmub aux handling *5235b56b7edrm/v3d: Add job to pending list if the reset was skipped *16857370b3iio: imu: st_lsm6dsx: fix possible lockup in st_lsm6dsx_read_tagged_fifo *6c4a500061iio: imu: st_lsm6dsx: fix possible lockup in st_lsm6dsx_read_fifo *2c66239cbfiio: adis16201: Correct inclinometer channel resolution *06acabd59biio: adc: ad7606: fix serial register access *30a4efc067drm/amd/display: Shift DMUB AUX reply command if necessary *02ad4ce144x86/mm: Eliminate window where TLB flushes may be inadvertently skipped *651d9b7d47staging: axis-fifo: Correct handling of tx_fifo_depth for size validation *0a73a6ac5fstaging: axis-fifo: Remove hardware resets for user errors *0f2c03bc1dstaging: iio: adc: ad7816: Correct conditional logic for store mode *a92a9a4a33Input: synaptics - enable InterTouch on TUXEDO InfinityBook Pro 14 v5 *4e904ea41fInput: synaptics - enable SMBus for HP Elitebook 850 G1 *7905a5fd76Input: synaptics - enable InterTouch on Dell Precision M3800 *ed506876c5Input: synaptics - enable InterTouch on Dynabook Portege X30L-G *f69db59eecInput: synaptics - enable InterTouch on Dynabook Portege X30-D *334d74a798Input: mtk-pmic-keys - fix possible null pointer dereference *03d71e1b24net: dsa: b53: fix learning on VLAN unaware bridges *3379b3ca2cnet: dsa: b53: always rejoin default untagged VLAN on bridge leave *4dc610122cnet: dsa: b53: fix VLAN ID for untagged vlan on bridge leave *55c845e76fnet: dsa: b53: fix flushing old pvid VLAN on pvid change *7f622ae738net: dsa: b53: fix clearing PVID of a port *aad87c94benet: dsa: b53: allow leaky reserved multicast *de1067cc8cbpf: Scrub packet on bpf_redirect_peer *aa77294b0fnetfilter: ipset: fix region locking in hash types *7d0032112aipvs: fix uninit-value for saddr in do_output_route4 *6e67f25c11ipv4: Drop tos parameter from flowi4_update_output() *21988c712acan: gw: fix RCU/BH usage in cgw_create_job() *3df065841crcu/kvfree: Add kvfree_rcu_mightsleep() and kfree_rcu_mightsleep() *e50ee08fafcan: mcp251xfd: fix TDC setting for low data bit rates *a51dc9669fgre: Fix again IPv6 link-local address generation. *c928dd4f6bsch_htb: make htb_deactivate() idempotent *facf22c1a3ksmbd: fix memory leak in parse_lease_state() *bca8df998copenvswitch: Fix unsafe attribute parsing in output_userspace() *7f61da79dfksmbd: prevent out-of-bounds stream writes by validating *pos *7fbb439ee2can: mcp251xfd: mcp251xfd_remove(): fix order of unregistration calls *0de5d055d4can: mcan: m_can_class_unregister(): fix order of unregistration calls *9f9d1ddee8arm64: dts: imx8mm-verdin: Link reg_usdhc2_vqmmc to usdhc2 *b173204aaddm: add missing unlock on in dm_keyslot_evict() Change-Id: Ibf2bcf5be1d871f03b6b19cd8bd8d1c3cd240fa5 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -514,6 +514,7 @@ Description: information about CPUs heterogeneity.
|
||||
|
||||
What: /sys/devices/system/cpu/vulnerabilities
|
||||
/sys/devices/system/cpu/vulnerabilities/gather_data_sampling
|
||||
/sys/devices/system/cpu/vulnerabilities/indirect_target_selection
|
||||
/sys/devices/system/cpu/vulnerabilities/itlb_multihit
|
||||
/sys/devices/system/cpu/vulnerabilities/l1tf
|
||||
/sys/devices/system/cpu/vulnerabilities/mds
|
||||
|
||||
@@ -22,3 +22,4 @@ are configurable at compile, boot or run time.
|
||||
gather_data_sampling.rst
|
||||
srso
|
||||
reg-file-data-sampling
|
||||
indirect-target-selection
|
||||
|
||||
156
Documentation/admin-guide/hw-vuln/indirect-target-selection.rst
Normal file
156
Documentation/admin-guide/hw-vuln/indirect-target-selection.rst
Normal file
@@ -0,0 +1,156 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
Indirect Target Selection (ITS)
|
||||
===============================
|
||||
|
||||
ITS is a vulnerability in some Intel CPUs that support Enhanced IBRS and were
|
||||
released before Alder Lake. ITS may allow an attacker to control the prediction
|
||||
of indirect branches and RETs located in the lower half of a cacheline.
|
||||
|
||||
ITS is assigned CVE-2024-28956 with a CVSS score of 4.7 (Medium).
|
||||
|
||||
Scope of Impact
|
||||
---------------
|
||||
- **eIBRS Guest/Host Isolation**: Indirect branches in KVM/kernel may still be
|
||||
predicted with unintended target corresponding to a branch in the guest.
|
||||
|
||||
- **Intra-Mode BTI**: In-kernel training such as through cBPF or other native
|
||||
gadgets.
|
||||
|
||||
- **Indirect Branch Prediction Barrier (IBPB)**: After an IBPB, indirect
|
||||
branches may still be predicted with targets corresponding to direct branches
|
||||
executed prior to the IBPB. This is fixed by the IPU 2025.1 microcode, which
|
||||
should be available via distro updates. Alternatively microcode can be
|
||||
obtained from Intel's github repository [#f1]_.
|
||||
|
||||
Affected CPUs
|
||||
-------------
|
||||
Below is the list of ITS affected CPUs [#f2]_ [#f3]_:
|
||||
|
||||
======================== ============ ==================== ===============
|
||||
Common name Family_Model eIBRS Intra-mode BTI
|
||||
Guest/Host Isolation
|
||||
======================== ============ ==================== ===============
|
||||
SKYLAKE_X (step >= 6) 06_55H Affected Affected
|
||||
ICELAKE_X 06_6AH Not affected Affected
|
||||
ICELAKE_D 06_6CH Not affected Affected
|
||||
ICELAKE_L 06_7EH Not affected Affected
|
||||
TIGERLAKE_L 06_8CH Not affected Affected
|
||||
TIGERLAKE 06_8DH Not affected Affected
|
||||
KABYLAKE_L (step >= 12) 06_8EH Affected Affected
|
||||
KABYLAKE (step >= 13) 06_9EH Affected Affected
|
||||
COMETLAKE 06_A5H Affected Affected
|
||||
COMETLAKE_L 06_A6H Affected Affected
|
||||
ROCKETLAKE 06_A7H Not affected Affected
|
||||
======================== ============ ==================== ===============
|
||||
|
||||
- All affected CPUs enumerate Enhanced IBRS feature.
|
||||
- IBPB isolation is affected on all ITS affected CPUs, and need a microcode
|
||||
update for mitigation.
|
||||
- None of the affected CPUs enumerate BHI_CTRL which was introduced in Golden
|
||||
Cove (Alder Lake and Sapphire Rapids). This can help guests to determine the
|
||||
host's affected status.
|
||||
- Intel Atom CPUs are not affected by ITS.
|
||||
|
||||
Mitigation
|
||||
----------
|
||||
As only the indirect branches and RETs that have their last byte of instruction
|
||||
in the lower half of the cacheline are vulnerable to ITS, the basic idea behind
|
||||
the mitigation is to not allow indirect branches in the lower half.
|
||||
|
||||
This is achieved by relying on existing retpoline support in the kernel, and in
|
||||
compilers. ITS-vulnerable retpoline sites are runtime patched to point to newly
|
||||
added ITS-safe thunks. These safe thunks consists of indirect branch in the
|
||||
second half of the cacheline. Not all retpoline sites are patched to thunks, if
|
||||
a retpoline site is evaluated to be ITS-safe, it is replaced with an inline
|
||||
indirect branch.
|
||||
|
||||
Dynamic thunks
|
||||
~~~~~~~~~~~~~~
|
||||
From a dynamically allocated pool of safe-thunks, each vulnerable site is
|
||||
replaced with a new thunk, such that they get a unique address. This could
|
||||
improve the branch prediction accuracy. Also, it is a defense-in-depth measure
|
||||
against aliasing.
|
||||
|
||||
Note, for simplicity, indirect branches in eBPF programs are always replaced
|
||||
with a jump to a static thunk in __x86_indirect_its_thunk_array. If required,
|
||||
in future this can be changed to use dynamic thunks.
|
||||
|
||||
All vulnerable RETs are replaced with a static thunk, they do not use dynamic
|
||||
thunks. This is because RETs get their prediction from RSB mostly that does not
|
||||
depend on source address. RETs that underflow RSB may benefit from dynamic
|
||||
thunks. But, RETs significantly outnumber indirect branches, and any benefit
|
||||
from a unique source address could be outweighed by the increased icache
|
||||
footprint and iTLB pressure.
|
||||
|
||||
Retpoline
|
||||
~~~~~~~~~
|
||||
Retpoline sequence also mitigates ITS-unsafe indirect branches. For this
|
||||
reason, when retpoline is enabled, ITS mitigation only relocates the RETs to
|
||||
safe thunks. Unless user requested the RSB-stuffing mitigation.
|
||||
|
||||
Mitigation in guests
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
All guests deploy ITS mitigation by default, irrespective of eIBRS enumeration
|
||||
and Family/Model of the guest. This is because eIBRS feature could be hidden
|
||||
from a guest. One exception to this is when a guest enumerates BHI_DIS_S, which
|
||||
indicates that the guest is running on an unaffected host.
|
||||
|
||||
To prevent guests from unnecessarily deploying the mitigation on unaffected
|
||||
platforms, Intel has defined ITS_NO bit(62) in MSR IA32_ARCH_CAPABILITIES. When
|
||||
a guest sees this bit set, it should not enumerate the ITS bug. Note, this bit
|
||||
is not set by any hardware, but is **intended for VMMs to synthesize** it for
|
||||
guests as per the host's affected status.
|
||||
|
||||
Mitigation options
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
The ITS mitigation can be controlled using the "indirect_target_selection"
|
||||
kernel parameter. The available options are:
|
||||
|
||||
======== ===================================================================
|
||||
on (default) Deploy the "Aligned branch/return thunks" mitigation.
|
||||
If spectre_v2 mitigation enables retpoline, aligned-thunks are only
|
||||
deployed for the affected RET instructions. Retpoline mitigates
|
||||
indirect branches.
|
||||
|
||||
off Disable ITS mitigation.
|
||||
|
||||
vmexit Equivalent to "=on" if the CPU is affected by guest/host isolation
|
||||
part of ITS. Otherwise, mitigation is not deployed. This option is
|
||||
useful when host userspace is not in the threat model, and only
|
||||
attacks from guest to host are considered.
|
||||
|
||||
force Force the ITS bug and deploy the default mitigation.
|
||||
======== ===================================================================
|
||||
|
||||
Sysfs reporting
|
||||
---------------
|
||||
|
||||
The sysfs file showing ITS mitigation status is:
|
||||
|
||||
/sys/devices/system/cpu/vulnerabilities/indirect_target_selection
|
||||
|
||||
Note, microcode mitigation status is not reported in this file.
|
||||
|
||||
The possible values in this file are:
|
||||
|
||||
.. list-table::
|
||||
|
||||
* - Not affected
|
||||
- The processor is not vulnerable.
|
||||
* - Vulnerable
|
||||
- System is vulnerable and no mitigation has been applied.
|
||||
* - Vulnerable, KVM: Not affected
|
||||
- System is vulnerable to intra-mode BTI, but not affected by eIBRS
|
||||
guest/host isolation.
|
||||
* - Mitigation: Aligned branch/return thunks
|
||||
- The mitigation is enabled, affected indirect branches and RETs are
|
||||
relocated to safe thunks.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [#f1] Microcode repository - https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files
|
||||
|
||||
.. [#f2] Affected Processors list - https://www.intel.com/content/www/us/en/developer/topic-technology/software-security-guidance/processors-affected-consolidated-product-cpu-model.html
|
||||
|
||||
.. [#f3] Affected Processors list (machine readable) - https://github.com/intel/Intel-affected-processor-list
|
||||
@@ -2048,6 +2048,20 @@
|
||||
different crypto accelerators. This option can be used
|
||||
to achieve best performance for particular HW.
|
||||
|
||||
indirect_target_selection= [X86,Intel] Mitigation control for Indirect
|
||||
Target Selection(ITS) bug in Intel CPUs. Updated
|
||||
microcode is also required for a fix in IBPB.
|
||||
|
||||
on: Enable mitigation (default).
|
||||
off: Disable mitigation.
|
||||
force: Force the ITS bug and deploy default
|
||||
mitigation.
|
||||
vmexit: Only deploy mitigation if CPU is affected by
|
||||
guest/host isolation part of ITS.
|
||||
|
||||
For details see:
|
||||
Documentation/admin-guide/hw-vuln/indirect-target-selection.rst
|
||||
|
||||
init= [KNL]
|
||||
Format: <full_path>
|
||||
Run specified binary instead of /sbin/init as init
|
||||
@@ -3311,6 +3325,7 @@
|
||||
expose users to several CPU vulnerabilities.
|
||||
Equivalent to: if nokaslr then kpti=0 [ARM64]
|
||||
gather_data_sampling=off [X86]
|
||||
indirect_target_selection=off [X86]
|
||||
kvm.nx_huge_pages=off [X86]
|
||||
l1tf=off [X86]
|
||||
mds=off [X86]
|
||||
@@ -5833,6 +5848,8 @@
|
||||
|
||||
Selecting 'on' will also enable the mitigation
|
||||
against user space to user space task attacks.
|
||||
Selecting specific mitigation does not force enable
|
||||
user mitigations.
|
||||
|
||||
Selecting 'off' will disable both the kernel and
|
||||
the user space protections.
|
||||
|
||||
@@ -32,12 +32,12 @@ Temperature sensors and fans can be queried and set via the standard
|
||||
=============================== ======= =======================================
|
||||
Name Perm Description
|
||||
=============================== ======= =======================================
|
||||
fan[1-3]_input RO Fan speed in RPM.
|
||||
fan[1-3]_label RO Fan label.
|
||||
fan[1-3]_min RO Minimal Fan speed in RPM
|
||||
fan[1-3]_max RO Maximal Fan speed in RPM
|
||||
fan[1-3]_target RO Expected Fan speed in RPM
|
||||
pwm[1-3] RW Control the fan PWM duty-cycle.
|
||||
fan[1-4]_input RO Fan speed in RPM.
|
||||
fan[1-4]_label RO Fan label.
|
||||
fan[1-4]_min RO Minimal Fan speed in RPM
|
||||
fan[1-4]_max RO Maximal Fan speed in RPM
|
||||
fan[1-4]_target RO Expected Fan speed in RPM
|
||||
pwm[1-4] RW Control the fan PWM duty-cycle.
|
||||
pwm1_enable WO Enable or disable automatic BIOS fan
|
||||
control (not supported on all laptops,
|
||||
see below for details).
|
||||
@@ -93,7 +93,7 @@ Again, when you find new codes, we'd be happy to have your patches!
|
||||
---------------------------
|
||||
|
||||
The driver also exports the fans as thermal cooling devices with
|
||||
``type`` set to ``dell-smm-fan[1-3]``. This allows for easy fan control
|
||||
``type`` set to ``dell-smm-fan[1-4]``. This allows for easy fan control
|
||||
using one of the thermal governors.
|
||||
|
||||
Module parameters
|
||||
|
||||
14
Makefile
14
Makefile
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 1
|
||||
SUBLEVEL = 138
|
||||
SUBLEVEL = 141
|
||||
EXTRAVERSION =
|
||||
NAME = Curry Ramen
|
||||
|
||||
@@ -895,6 +895,18 @@ ifdef CONFIG_CC_IS_CLANG
|
||||
KBUILD_CPPFLAGS += -Qunused-arguments
|
||||
# The kernel builds with '-std=gnu11' so use of GNU extensions is acceptable.
|
||||
KBUILD_CFLAGS += -Wno-gnu
|
||||
|
||||
# Clang may emit a warning when a const variable, such as the dummy variables
|
||||
# in typecheck(), or const member of an aggregate type are not initialized,
|
||||
# which can result in unexpected behavior. However, in many audited cases of
|
||||
# the "field" variant of the warning, this is intentional because the field is
|
||||
# never used within a particular call path, the field is within a union with
|
||||
# other non-const members, or the containing object is not const so the field
|
||||
# can be modified via memcpy() / memset(). While the variable warning also gets
|
||||
# disabled with this same switch, there should not be too much coverage lost
|
||||
# because -Wuninitialized will still flag when an uninitialized const variable
|
||||
# is used.
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, default-const-init-unsafe)
|
||||
else
|
||||
|
||||
# gcc inanely warns about local variables called 'main'
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
reg = <0x54400000 0x00040000>;
|
||||
clocks = <&tegra_car TEGRA114_CLK_DSIB>,
|
||||
<&tegra_car TEGRA114_CLK_DSIBLP>,
|
||||
<&tegra_car TEGRA114_CLK_PLL_D2_OUT0>;
|
||||
<&tegra_car TEGRA114_CLK_PLL_D_OUT0>;
|
||||
clock-names = "dsi", "lp", "parent";
|
||||
resets = <&tegra_car 82>;
|
||||
reset-names = "dsi";
|
||||
|
||||
@@ -537,11 +537,12 @@ extern u32 at91_pm_suspend_in_sram_sz;
|
||||
|
||||
static int at91_suspend_finish(unsigned long val)
|
||||
{
|
||||
unsigned char modified_gray_code[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05, 0x0c, 0x0d,
|
||||
0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09, 0x18, 0x19, 0x1a, 0x1b,
|
||||
0x1e, 0x1f, 0x1c, 0x1d, 0x14, 0x15, 0x16, 0x17, 0x12, 0x13,
|
||||
0x10, 0x11,
|
||||
/* SYNOPSYS workaround to fix a bug in the calibration logic */
|
||||
unsigned char modified_fix_code[] = {
|
||||
0x00, 0x01, 0x01, 0x06, 0x07, 0x0c, 0x06, 0x07, 0x0b, 0x18,
|
||||
0x0a, 0x0b, 0x0c, 0x0d, 0x0d, 0x0a, 0x13, 0x13, 0x12, 0x13,
|
||||
0x14, 0x15, 0x15, 0x12, 0x18, 0x19, 0x19, 0x1e, 0x1f, 0x14,
|
||||
0x1e, 0x1f,
|
||||
};
|
||||
unsigned int tmp, index;
|
||||
int i;
|
||||
@@ -552,25 +553,25 @@ static int at91_suspend_finish(unsigned long val)
|
||||
* restore the ZQ0SR0 with the value saved here. But the
|
||||
* calibration is buggy and restoring some values from ZQ0SR0
|
||||
* is forbidden and risky thus we need to provide processed
|
||||
* values for these (modified gray code values).
|
||||
* values for these.
|
||||
*/
|
||||
tmp = readl(soc_pm.data.ramc_phy + DDR3PHY_ZQ0SR0);
|
||||
|
||||
/* Store pull-down output impedance select. */
|
||||
index = (tmp >> DDR3PHY_ZQ0SR0_PDO_OFF) & 0x1f;
|
||||
soc_pm.bu->ddr_phy_calibration[0] = modified_gray_code[index];
|
||||
soc_pm.bu->ddr_phy_calibration[0] = modified_fix_code[index] << DDR3PHY_ZQ0SR0_PDO_OFF;
|
||||
|
||||
/* Store pull-up output impedance select. */
|
||||
index = (tmp >> DDR3PHY_ZQ0SR0_PUO_OFF) & 0x1f;
|
||||
soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
|
||||
soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SR0_PUO_OFF;
|
||||
|
||||
/* Store pull-down on-die termination impedance select. */
|
||||
index = (tmp >> DDR3PHY_ZQ0SR0_PDODT_OFF) & 0x1f;
|
||||
soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
|
||||
soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SR0_PDODT_OFF;
|
||||
|
||||
/* Store pull-up on-die termination impedance select. */
|
||||
index = (tmp >> DDR3PHY_ZQ0SRO_PUODT_OFF) & 0x1f;
|
||||
soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
|
||||
soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SRO_PUODT_OFF;
|
||||
|
||||
/*
|
||||
* The 1st 8 words of memory might get corrupted in the process
|
||||
|
||||
@@ -151,28 +151,12 @@
|
||||
vcc-pg-supply = <®_aldo1>;
|
||||
};
|
||||
|
||||
&r_ir {
|
||||
linux,rc-map-name = "rc-beelink-gs1";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&r_pio {
|
||||
/*
|
||||
* FIXME: We can't add that supply for now since it would
|
||||
* create a circular dependency between pinctrl, the regulator
|
||||
* and the RSB Bus.
|
||||
*
|
||||
* vcc-pl-supply = <®_aldo1>;
|
||||
*/
|
||||
vcc-pm-supply = <®_aldo1>;
|
||||
};
|
||||
|
||||
&r_rsb {
|
||||
&r_i2c {
|
||||
status = "okay";
|
||||
|
||||
axp805: pmic@745 {
|
||||
axp805: pmic@36 {
|
||||
compatible = "x-powers,axp805", "x-powers,axp806";
|
||||
reg = <0x745>;
|
||||
reg = <0x36>;
|
||||
interrupt-parent = <&r_intc>;
|
||||
interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-controller;
|
||||
@@ -290,6 +274,22 @@
|
||||
};
|
||||
};
|
||||
|
||||
&r_ir {
|
||||
linux,rc-map-name = "rc-beelink-gs1";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&r_pio {
|
||||
/*
|
||||
* PL0 and PL1 are used for PMIC I2C
|
||||
* don't enable the pl-supply else
|
||||
* it will fail at boot
|
||||
*
|
||||
* vcc-pl-supply = <®_aldo1>;
|
||||
*/
|
||||
vcc-pm-supply = <®_aldo1>;
|
||||
};
|
||||
|
||||
&spdif {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&spdif_tx_pin>;
|
||||
|
||||
@@ -175,16 +175,12 @@
|
||||
vcc-pg-supply = <®_vcc_wifi_io>;
|
||||
};
|
||||
|
||||
&r_ir {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&r_rsb {
|
||||
&r_i2c {
|
||||
status = "okay";
|
||||
|
||||
axp805: pmic@745 {
|
||||
axp805: pmic@36 {
|
||||
compatible = "x-powers,axp805", "x-powers,axp806";
|
||||
reg = <0x745>;
|
||||
reg = <0x36>;
|
||||
interrupt-parent = <&r_intc>;
|
||||
interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-controller;
|
||||
@@ -295,6 +291,10 @@
|
||||
};
|
||||
};
|
||||
|
||||
&r_ir {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rtc {
|
||||
clocks = <&ext_osc32k>;
|
||||
};
|
||||
|
||||
@@ -112,20 +112,12 @@
|
||||
vcc-pg-supply = <®_aldo1>;
|
||||
};
|
||||
|
||||
&r_ir {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&r_pio {
|
||||
vcc-pm-supply = <®_bldo3>;
|
||||
};
|
||||
|
||||
&r_rsb {
|
||||
&r_i2c {
|
||||
status = "okay";
|
||||
|
||||
axp805: pmic@745 {
|
||||
axp805: pmic@36 {
|
||||
compatible = "x-powers,axp805", "x-powers,axp806";
|
||||
reg = <0x745>;
|
||||
reg = <0x36>;
|
||||
interrupt-parent = <&r_intc>;
|
||||
interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-controller;
|
||||
@@ -240,6 +232,14 @@
|
||||
};
|
||||
};
|
||||
|
||||
&r_ir {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&r_pio {
|
||||
vcc-pm-supply = <®_bldo3>;
|
||||
};
|
||||
|
||||
&rtc {
|
||||
clocks = <&ext_osc32k>;
|
||||
};
|
||||
|
||||
@@ -144,6 +144,19 @@
|
||||
startup-delay-us = <20000>;
|
||||
};
|
||||
|
||||
reg_usdhc2_vqmmc: regulator-usdhc2-vqmmc {
|
||||
compatible = "regulator-gpio";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_usdhc2_vsel>;
|
||||
gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
states = <1800000 0x1>,
|
||||
<3300000 0x0>;
|
||||
regulator-name = "PMIC_USDHC_VSELECT";
|
||||
vin-supply = <®_nvcc_sd>;
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
@@ -262,7 +275,7 @@
|
||||
"SODIMM_19",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"PMIC_USDHC_VSELECT",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
@@ -788,6 +801,7 @@
|
||||
pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_cd>;
|
||||
pinctrl-3 = <&pinctrl_usdhc2_sleep>, <&pinctrl_usdhc2_cd_sleep>;
|
||||
vmmc-supply = <®_usdhc2_vmmc>;
|
||||
vqmmc-supply = <®_usdhc2_vqmmc>;
|
||||
};
|
||||
|
||||
&wdog1 {
|
||||
@@ -1210,13 +1224,17 @@
|
||||
<MX8MM_IOMUXC_NAND_CLE_GPIO3_IO5 0x6>; /* SODIMM 76 */
|
||||
};
|
||||
|
||||
pinctrl_usdhc2_vsel: usdhc2vselgrp {
|
||||
fsl,pins =
|
||||
<MX8MM_IOMUXC_GPIO1_IO04_GPIO1_IO4 0x10>; /* PMIC_USDHC_VSELECT */
|
||||
};
|
||||
|
||||
/*
|
||||
* Note: Due to ERR050080 we use discrete external on-module resistors pulling-up to the
|
||||
* on-module +V3.3_1.8_SD (LDO5) rail and explicitly disable the internal pull-ups here.
|
||||
*/
|
||||
pinctrl_usdhc2: usdhc2grp {
|
||||
fsl,pins =
|
||||
<MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x10>,
|
||||
<MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x90>, /* SODIMM 78 */
|
||||
<MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x90>, /* SODIMM 74 */
|
||||
<MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x90>, /* SODIMM 80 */
|
||||
@@ -1227,7 +1245,6 @@
|
||||
|
||||
pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
|
||||
fsl,pins =
|
||||
<MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x10>,
|
||||
<MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x94>,
|
||||
<MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x94>,
|
||||
<MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x94>,
|
||||
@@ -1238,7 +1255,6 @@
|
||||
|
||||
pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
|
||||
fsl,pins =
|
||||
<MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x10>,
|
||||
<MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x96>,
|
||||
<MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x96>,
|
||||
<MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x96>,
|
||||
@@ -1250,7 +1266,6 @@
|
||||
/* Avoid backfeeding with removed card power */
|
||||
pinctrl_usdhc2_sleep: usdhc2slpgrp {
|
||||
fsl,pins =
|
||||
<MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x0>,
|
||||
<MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x0>,
|
||||
<MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x0>,
|
||||
<MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x0>,
|
||||
|
||||
@@ -1631,7 +1631,7 @@
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-always-on;
|
||||
gpio = <&exp1 14 GPIO_ACTIVE_HIGH>;
|
||||
gpio = <&exp1 9 GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
vin-supply = <&vdd_1v8>;
|
||||
};
|
||||
|
||||
@@ -421,7 +421,7 @@
|
||||
no-map;
|
||||
};
|
||||
|
||||
pil_camera_mem: mmeory@85200000 {
|
||||
pil_camera_mem: memory@85200000 {
|
||||
reg = <0x0 0x85200000 0x0 0x500000>;
|
||||
no-map;
|
||||
};
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
#define ARM_CPU_PART_CORTEX_A78AE 0xD42
|
||||
#define ARM_CPU_PART_CORTEX_X1 0xD44
|
||||
#define ARM_CPU_PART_CORTEX_A510 0xD46
|
||||
#define ARM_CPU_PART_CORTEX_X1C 0xD4C
|
||||
#define ARM_CPU_PART_CORTEX_A520 0xD80
|
||||
#define ARM_CPU_PART_CORTEX_A710 0xD47
|
||||
#define ARM_CPU_PART_CORTEX_A715 0xD4D
|
||||
@@ -131,6 +132,7 @@
|
||||
#define FUJITSU_CPU_PART_A64FX 0x001
|
||||
|
||||
#define HISI_CPU_PART_TSV110 0xD01
|
||||
#define HISI_CPU_PART_HIP09 0xD02
|
||||
|
||||
#define APPLE_CPU_PART_M1_ICESTORM 0x022
|
||||
#define APPLE_CPU_PART_M1_FIRESTORM 0x023
|
||||
@@ -159,6 +161,7 @@
|
||||
#define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE)
|
||||
#define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1)
|
||||
#define MIDR_CORTEX_A510 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A510)
|
||||
#define MIDR_CORTEX_X1C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1C)
|
||||
#define MIDR_CORTEX_A520 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A520)
|
||||
#define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710)
|
||||
#define MIDR_CORTEX_A715 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A715)
|
||||
@@ -199,6 +202,7 @@
|
||||
#define MIDR_NVIDIA_CARMEL MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_CARMEL)
|
||||
#define MIDR_FUJITSU_A64FX MIDR_CPU_MODEL(ARM_CPU_IMP_FUJITSU, FUJITSU_CPU_PART_A64FX)
|
||||
#define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110)
|
||||
#define MIDR_HISI_HIP09 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_HIP09)
|
||||
#define MIDR_APPLE_M1_ICESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM)
|
||||
#define MIDR_APPLE_M1_FIRESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM)
|
||||
#define MIDR_APPLE_M1_ICESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_PRO)
|
||||
|
||||
@@ -619,6 +619,7 @@ u32 aarch64_insn_gen_cas(enum aarch64_insn_register result,
|
||||
}
|
||||
#endif
|
||||
u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type);
|
||||
u32 aarch64_insn_gen_dsb(enum aarch64_insn_mb_type type);
|
||||
|
||||
s32 aarch64_get_branch_offset(u32 insn);
|
||||
u32 aarch64_set_branch_offset(u32 insn, s32 offset);
|
||||
|
||||
@@ -681,7 +681,8 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
|
||||
pr_err("%s:%d: bad pmd %016llx.\n", __FILE__, __LINE__, pmd_val(e))
|
||||
|
||||
#define pud_none(pud) (!pud_val(pud))
|
||||
#define pud_bad(pud) (!pud_table(pud))
|
||||
#define pud_bad(pud) ((pud_val(pud) & PUD_TYPE_MASK) != \
|
||||
PUD_TYPE_TABLE)
|
||||
#define pud_present(pud) pte_present(pud_pte(pud))
|
||||
#define pud_leaf(pud) (pud_present(pud) && !pud_table(pud))
|
||||
#define pud_valid(pud) pte_valid(pud_pte(pud))
|
||||
|
||||
@@ -96,6 +96,9 @@ enum mitigation_state arm64_get_meltdown_state(void);
|
||||
|
||||
enum mitigation_state arm64_get_spectre_bhb_state(void);
|
||||
bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, int scope);
|
||||
extern bool __nospectre_bhb;
|
||||
u8 get_spectre_bhb_loop_value(void);
|
||||
bool is_spectre_bhb_fw_mitigated(void);
|
||||
void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *__unused);
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASM_SPECTRE_H */
|
||||
|
||||
@@ -1234,8 +1234,10 @@ void fpsimd_release_task(struct task_struct *dead_task)
|
||||
*/
|
||||
void sme_alloc(struct task_struct *task, bool flush)
|
||||
{
|
||||
if (task->thread.za_state && flush) {
|
||||
memset(task->thread.za_state, 0, za_state_size(task));
|
||||
if (task->thread.za_state) {
|
||||
if (flush)
|
||||
memset(task->thread.za_state, 0,
|
||||
za_state_size(task));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -903,6 +903,7 @@ static u8 spectre_bhb_loop_affected(void)
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78AE),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_X1),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_X1C),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_X2),
|
||||
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
|
||||
@@ -915,6 +916,7 @@ static u8 spectre_bhb_loop_affected(void)
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A77),
|
||||
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1),
|
||||
MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_GOLD),
|
||||
MIDR_ALL_VERSIONS(MIDR_HISI_HIP09),
|
||||
{},
|
||||
};
|
||||
static const struct midr_range spectre_bhb_k11_list[] = {
|
||||
@@ -1010,6 +1012,11 @@ bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry,
|
||||
return true;
|
||||
}
|
||||
|
||||
u8 get_spectre_bhb_loop_value(void)
|
||||
{
|
||||
return max_bhb_k;
|
||||
}
|
||||
|
||||
static void this_cpu_set_vectors(enum arm64_bp_harden_el1_vectors slot)
|
||||
{
|
||||
const char *v = arm64_get_bp_hardening_vector(slot);
|
||||
@@ -1030,7 +1037,7 @@ static void this_cpu_set_vectors(enum arm64_bp_harden_el1_vectors slot)
|
||||
isb();
|
||||
}
|
||||
|
||||
static bool __read_mostly __nospectre_bhb;
|
||||
bool __read_mostly __nospectre_bhb;
|
||||
static int __init parse_spectre_bhb_param(char *str)
|
||||
{
|
||||
__nospectre_bhb = true;
|
||||
@@ -1108,6 +1115,11 @@ void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry)
|
||||
update_mitigation_state(&spectre_bhb_state, state);
|
||||
}
|
||||
|
||||
bool is_spectre_bhb_fw_mitigated(void)
|
||||
{
|
||||
return test_bit(BHB_FW, &system_bhb_mitigations);
|
||||
}
|
||||
|
||||
/* Patched to NOP when enabled */
|
||||
void noinstr spectre_bhb_patch_loop_mitigation_enable(struct alt_instr *alt,
|
||||
__le32 *origptr,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*
|
||||
* Copyright (C) 2014-2016 Zi Shen Lim <zlim.lnx@gmail.com>
|
||||
*/
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/printk.h>
|
||||
@@ -1630,43 +1631,41 @@ u32 aarch64_insn_gen_extr(enum aarch64_insn_variant variant,
|
||||
return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, Rm);
|
||||
}
|
||||
|
||||
static u32 __get_barrier_crm_val(enum aarch64_insn_mb_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case AARCH64_INSN_MB_SY:
|
||||
return 0xf;
|
||||
case AARCH64_INSN_MB_ST:
|
||||
return 0xe;
|
||||
case AARCH64_INSN_MB_LD:
|
||||
return 0xd;
|
||||
case AARCH64_INSN_MB_ISH:
|
||||
return 0xb;
|
||||
case AARCH64_INSN_MB_ISHST:
|
||||
return 0xa;
|
||||
case AARCH64_INSN_MB_ISHLD:
|
||||
return 0x9;
|
||||
case AARCH64_INSN_MB_NSH:
|
||||
return 0x7;
|
||||
case AARCH64_INSN_MB_NSHST:
|
||||
return 0x6;
|
||||
case AARCH64_INSN_MB_NSHLD:
|
||||
return 0x5;
|
||||
default:
|
||||
pr_err("%s: unknown barrier type %d\n", __func__, type);
|
||||
return AARCH64_BREAK_FAULT;
|
||||
}
|
||||
}
|
||||
|
||||
u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type)
|
||||
{
|
||||
u32 opt;
|
||||
u32 insn;
|
||||
|
||||
switch (type) {
|
||||
case AARCH64_INSN_MB_SY:
|
||||
opt = 0xf;
|
||||
break;
|
||||
case AARCH64_INSN_MB_ST:
|
||||
opt = 0xe;
|
||||
break;
|
||||
case AARCH64_INSN_MB_LD:
|
||||
opt = 0xd;
|
||||
break;
|
||||
case AARCH64_INSN_MB_ISH:
|
||||
opt = 0xb;
|
||||
break;
|
||||
case AARCH64_INSN_MB_ISHST:
|
||||
opt = 0xa;
|
||||
break;
|
||||
case AARCH64_INSN_MB_ISHLD:
|
||||
opt = 0x9;
|
||||
break;
|
||||
case AARCH64_INSN_MB_NSH:
|
||||
opt = 0x7;
|
||||
break;
|
||||
case AARCH64_INSN_MB_NSHST:
|
||||
opt = 0x6;
|
||||
break;
|
||||
case AARCH64_INSN_MB_NSHLD:
|
||||
opt = 0x5;
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: unknown dmb type %d\n", __func__, type);
|
||||
opt = __get_barrier_crm_val(type);
|
||||
if (opt == AARCH64_BREAK_FAULT)
|
||||
return AARCH64_BREAK_FAULT;
|
||||
}
|
||||
|
||||
insn = aarch64_insn_get_dmb_value();
|
||||
insn &= ~GENMASK(11, 8);
|
||||
@@ -1674,3 +1673,18 @@ u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type)
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
u32 aarch64_insn_gen_dsb(enum aarch64_insn_mb_type type)
|
||||
{
|
||||
u32 opt, insn;
|
||||
|
||||
opt = __get_barrier_crm_val(type);
|
||||
if (opt == AARCH64_BREAK_FAULT)
|
||||
return AARCH64_BREAK_FAULT;
|
||||
|
||||
insn = aarch64_insn_get_dsb_base_value();
|
||||
insn &= ~GENMASK(11, 8);
|
||||
insn |= (opt << 8);
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#define pr_fmt(fmt) "bpf_jit: " fmt
|
||||
|
||||
#include <linux/arm-smccc.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/filter.h>
|
||||
@@ -17,6 +18,7 @@
|
||||
#include <asm/asm-extable.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/debug-monitors.h>
|
||||
#include <asm/insn.h>
|
||||
#include <asm/patching.h>
|
||||
@@ -653,7 +655,51 @@ static void build_plt(struct jit_ctx *ctx)
|
||||
plt->target = (u64)&dummy_tramp;
|
||||
}
|
||||
|
||||
static void build_epilogue(struct jit_ctx *ctx)
|
||||
/* Clobbers BPF registers 1-4, aka x0-x3 */
|
||||
static void __maybe_unused build_bhb_mitigation(struct jit_ctx *ctx)
|
||||
{
|
||||
const u8 r1 = bpf2a64[BPF_REG_1]; /* aka x0 */
|
||||
u8 k = get_spectre_bhb_loop_value();
|
||||
|
||||
if (!IS_ENABLED(CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY) ||
|
||||
cpu_mitigations_off() || __nospectre_bhb ||
|
||||
arm64_get_spectre_v2_state() == SPECTRE_VULNERABLE)
|
||||
return;
|
||||
|
||||
if (capable(CAP_SYS_ADMIN))
|
||||
return;
|
||||
|
||||
if (supports_clearbhb(SCOPE_SYSTEM)) {
|
||||
emit(aarch64_insn_gen_hint(AARCH64_INSN_HINT_CLEARBHB), ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (k) {
|
||||
emit_a64_mov_i64(r1, k, ctx);
|
||||
emit(A64_B(1), ctx);
|
||||
emit(A64_SUBS_I(true, r1, r1, 1), ctx);
|
||||
emit(A64_B_(A64_COND_NE, -2), ctx);
|
||||
emit(aarch64_insn_gen_dsb(AARCH64_INSN_MB_ISH), ctx);
|
||||
emit(aarch64_insn_get_isb_value(), ctx);
|
||||
}
|
||||
|
||||
if (is_spectre_bhb_fw_mitigated()) {
|
||||
emit(A64_ORR_I(false, r1, AARCH64_INSN_REG_ZR,
|
||||
ARM_SMCCC_ARCH_WORKAROUND_3), ctx);
|
||||
switch (arm_smccc_1_1_get_conduit()) {
|
||||
case SMCCC_CONDUIT_HVC:
|
||||
emit(aarch64_insn_get_hvc_value(), ctx);
|
||||
break;
|
||||
case SMCCC_CONDUIT_SMC:
|
||||
emit(aarch64_insn_get_smc_value(), ctx);
|
||||
break;
|
||||
default:
|
||||
pr_err_once("Firmware mitigation enabled with unknown conduit\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void build_epilogue(struct jit_ctx *ctx, bool was_classic)
|
||||
{
|
||||
const u8 r0 = bpf2a64[BPF_REG_0];
|
||||
const u8 r6 = bpf2a64[BPF_REG_6];
|
||||
@@ -675,10 +721,13 @@ static void build_epilogue(struct jit_ctx *ctx)
|
||||
emit(A64_POP(r8, r9, A64_SP), ctx);
|
||||
emit(A64_POP(r6, r7, A64_SP), ctx);
|
||||
|
||||
if (was_classic)
|
||||
build_bhb_mitigation(ctx);
|
||||
|
||||
/* Restore FP/LR registers */
|
||||
emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx);
|
||||
|
||||
/* Set return value */
|
||||
/* Move the return value from bpf:r0 (aka x7) to x0 */
|
||||
emit(A64_MOV(1, A64_R(0), r0), ctx);
|
||||
|
||||
/* Authenticate lr */
|
||||
@@ -1527,7 +1576,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
}
|
||||
|
||||
ctx.epilogue_offset = ctx.idx;
|
||||
build_epilogue(&ctx);
|
||||
build_epilogue(&ctx, was_classic);
|
||||
build_plt(&ctx);
|
||||
|
||||
extable_align = __alignof__(struct exception_table_entry);
|
||||
@@ -1563,7 +1612,7 @@ skip_init_ctx:
|
||||
goto out_off;
|
||||
}
|
||||
|
||||
build_epilogue(&ctx);
|
||||
build_epilogue(&ctx, was_classic);
|
||||
build_plt(&ctx);
|
||||
|
||||
/* 3. Extra pass to validate JITed code. */
|
||||
@@ -1893,7 +1942,11 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
||||
emit(A64_STR64I(A64_R(20), A64_SP, regs_off + 8), ctx);
|
||||
|
||||
if (flags & BPF_TRAMP_F_CALL_ORIG) {
|
||||
emit_addr_mov_i64(A64_R(0), (const u64)im, ctx);
|
||||
/* for the first pass, assume the worst case */
|
||||
if (!ctx->image)
|
||||
ctx->idx += 4;
|
||||
else
|
||||
emit_a64_mov_i64(A64_R(0), (const u64)im, ctx);
|
||||
emit_call((const u64)__bpf_tramp_enter, ctx);
|
||||
}
|
||||
|
||||
@@ -1937,7 +1990,11 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
||||
|
||||
if (flags & BPF_TRAMP_F_CALL_ORIG) {
|
||||
im->ip_epilogue = ctx->image + ctx->idx;
|
||||
emit_addr_mov_i64(A64_R(0), (const u64)im, ctx);
|
||||
/* for the first pass, assume the worst case */
|
||||
if (!ctx->image)
|
||||
ctx->idx += 4;
|
||||
else
|
||||
emit_a64_mov_i64(A64_R(0), (const u64)im, ctx);
|
||||
emit_call((const u64)__bpf_tramp_exit, ctx);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ endif
|
||||
|
||||
ifdef CONFIG_64BIT
|
||||
ld-emul = $(64bit-emul)
|
||||
cflags-y += -mabi=lp64s
|
||||
cflags-y += -mabi=lp64s -mcmodel=normal
|
||||
endif
|
||||
|
||||
cflags-y += -pipe -msoft-float
|
||||
|
||||
@@ -54,7 +54,7 @@ static inline void instruction_pointer_set(struct pt_regs *regs, unsigned long v
|
||||
|
||||
/* Query offset/name of register from its name/offset */
|
||||
extern int regs_query_register_offset(const char *name);
|
||||
#define MAX_REG_OFFSET (offsetof(struct pt_regs, __last))
|
||||
#define MAX_REG_OFFSET (offsetof(struct pt_regs, __last) - sizeof(unsigned long))
|
||||
|
||||
/**
|
||||
* regs_get_register() - get register value from its offset
|
||||
|
||||
@@ -87,4 +87,20 @@ struct dyn_arch_ftrace {
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE */
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* CONFIG_FUNCTION_TRACER */
|
||||
|
||||
#ifdef CONFIG_FTRACE_SYSCALLS
|
||||
#ifndef __ASSEMBLY__
|
||||
/*
|
||||
* Some syscall entry functions on mips start with "__sys_" (fork and clone,
|
||||
* for instance). We should also match the sys_ variant with those.
|
||||
*/
|
||||
#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
|
||||
static inline bool arch_syscall_match_sym_name(const char *sym,
|
||||
const char *name)
|
||||
{
|
||||
return !strcmp(sym, name) ||
|
||||
(!strncmp(sym, "__sys_", 6) && !strcmp(sym + 6, name + 4));
|
||||
}
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* CONFIG_FTRACE_SYSCALLS */
|
||||
#endif /* _ASM_MIPS_FTRACE_H */
|
||||
|
||||
@@ -65,7 +65,8 @@ static inline void instruction_pointer_set(struct pt_regs *regs,
|
||||
|
||||
/* Query offset/name of register from its name/offset */
|
||||
extern int regs_query_register_offset(const char *name);
|
||||
#define MAX_REG_OFFSET (offsetof(struct pt_regs, __last))
|
||||
#define MAX_REG_OFFSET \
|
||||
(offsetof(struct pt_regs, __last) - sizeof(unsigned long))
|
||||
|
||||
/**
|
||||
* regs_get_register() - get register value from its offset
|
||||
|
||||
@@ -56,10 +56,7 @@ static DEFINE_PER_CPU_ALIGNED(u32*, ready_count);
|
||||
/* Indicates online CPUs coupled with the current CPU */
|
||||
static DEFINE_PER_CPU_ALIGNED(cpumask_t, online_coupled);
|
||||
|
||||
/*
|
||||
* Used to synchronize entry to deep idle states. Actually per-core rather
|
||||
* than per-CPU.
|
||||
*/
|
||||
/* Used to synchronize entry to deep idle states */
|
||||
static DEFINE_PER_CPU_ALIGNED(atomic_t, pm_barrier);
|
||||
|
||||
/* Saved CPU state across the CPS_PM_POWER_GATED state */
|
||||
@@ -118,9 +115,10 @@ int cps_pm_enter_state(enum cps_pm_state state)
|
||||
cps_nc_entry_fn entry;
|
||||
struct core_boot_config *core_cfg;
|
||||
struct vpe_boot_config *vpe_cfg;
|
||||
atomic_t *barrier;
|
||||
|
||||
/* Check that there is an entry function for this state */
|
||||
entry = per_cpu(nc_asm_enter, core)[state];
|
||||
entry = per_cpu(nc_asm_enter, cpu)[state];
|
||||
if (!entry)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -156,7 +154,7 @@ int cps_pm_enter_state(enum cps_pm_state state)
|
||||
smp_mb__after_atomic();
|
||||
|
||||
/* Create a non-coherent mapping of the core ready_count */
|
||||
core_ready_count = per_cpu(ready_count, core);
|
||||
core_ready_count = per_cpu(ready_count, cpu);
|
||||
nc_addr = kmap_noncoherent(virt_to_page(core_ready_count),
|
||||
(unsigned long)core_ready_count);
|
||||
nc_addr += ((unsigned long)core_ready_count & ~PAGE_MASK);
|
||||
@@ -164,7 +162,8 @@ int cps_pm_enter_state(enum cps_pm_state state)
|
||||
|
||||
/* Ensure ready_count is zero-initialised before the assembly runs */
|
||||
WRITE_ONCE(*nc_core_ready_count, 0);
|
||||
coupled_barrier(&per_cpu(pm_barrier, core), online);
|
||||
barrier = &per_cpu(pm_barrier, cpumask_first(&cpu_sibling_map[cpu]));
|
||||
coupled_barrier(barrier, online);
|
||||
|
||||
/* Run the generated entry code */
|
||||
left = entry(online, nc_core_ready_count);
|
||||
@@ -635,12 +634,14 @@ out_err:
|
||||
|
||||
static int cps_pm_online_cpu(unsigned int cpu)
|
||||
{
|
||||
enum cps_pm_state state;
|
||||
unsigned core = cpu_core(&cpu_data[cpu]);
|
||||
unsigned int sibling, core;
|
||||
void *entry_fn, *core_rc;
|
||||
enum cps_pm_state state;
|
||||
|
||||
core = cpu_core(&cpu_data[cpu]);
|
||||
|
||||
for (state = CPS_PM_NC_WAIT; state < CPS_PM_STATE_COUNT; state++) {
|
||||
if (per_cpu(nc_asm_enter, core)[state])
|
||||
if (per_cpu(nc_asm_enter, cpu)[state])
|
||||
continue;
|
||||
if (!test_bit(state, state_support))
|
||||
continue;
|
||||
@@ -652,16 +653,19 @@ static int cps_pm_online_cpu(unsigned int cpu)
|
||||
clear_bit(state, state_support);
|
||||
}
|
||||
|
||||
per_cpu(nc_asm_enter, core)[state] = entry_fn;
|
||||
for_each_cpu(sibling, &cpu_sibling_map[cpu])
|
||||
per_cpu(nc_asm_enter, sibling)[state] = entry_fn;
|
||||
}
|
||||
|
||||
if (!per_cpu(ready_count, core)) {
|
||||
if (!per_cpu(ready_count, cpu)) {
|
||||
core_rc = kmalloc(sizeof(u32), GFP_KERNEL);
|
||||
if (!core_rc) {
|
||||
pr_err("Failed allocate core %u ready_count\n", core);
|
||||
return -ENOMEM;
|
||||
}
|
||||
per_cpu(ready_count, core) = core_rc;
|
||||
|
||||
for_each_cpu(sibling, &cpu_sibling_map[cpu])
|
||||
per_cpu(ready_count, sibling) = core_rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -2974,11 +2974,11 @@ static void __init fixup_device_tree_pmac(void)
|
||||
char type[8];
|
||||
phandle node;
|
||||
|
||||
// Some pmacs are missing #size-cells on escc nodes
|
||||
// Some pmacs are missing #size-cells on escc or i2s nodes
|
||||
for (node = 0; prom_next_node(&node); ) {
|
||||
type[0] = '\0';
|
||||
prom_getprop(node, "device_type", type, sizeof(type));
|
||||
if (prom_strcmp(type, "escc"))
|
||||
if (prom_strcmp(type, "escc") && prom_strcmp(type, "i2s"))
|
||||
continue;
|
||||
|
||||
if (prom_getproplen(node, "#size-cells") != PROM_ERROR)
|
||||
|
||||
@@ -2229,6 +2229,10 @@ static struct pmu power_pmu = {
|
||||
#define PERF_SAMPLE_ADDR_TYPE (PERF_SAMPLE_ADDR | \
|
||||
PERF_SAMPLE_PHYS_ADDR | \
|
||||
PERF_SAMPLE_DATA_PAGE_SIZE)
|
||||
|
||||
#define SIER_TYPE_SHIFT 15
|
||||
#define SIER_TYPE_MASK (0x7ull << SIER_TYPE_SHIFT)
|
||||
|
||||
/*
|
||||
* A counter has overflowed; update its count and record
|
||||
* things if requested. Note that interrupts are hard-disabled
|
||||
@@ -2297,6 +2301,22 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
|
||||
is_kernel_addr(mfspr(SPRN_SIAR)))
|
||||
record = 0;
|
||||
|
||||
/*
|
||||
* SIER[46-48] presents instruction type of the sampled instruction.
|
||||
* In ISA v3.0 and before values "0" and "7" are considered reserved.
|
||||
* In ISA v3.1, value "7" has been used to indicate "larx/stcx".
|
||||
* Drop the sample if "type" has reserved values for this field with a
|
||||
* ISA version check.
|
||||
*/
|
||||
if (event->attr.sample_type & PERF_SAMPLE_DATA_SRC &&
|
||||
ppmu->get_mem_data_src) {
|
||||
val = (regs->dar & SIER_TYPE_MASK) >> SIER_TYPE_SHIFT;
|
||||
if (val == 0 || (val == 7 && !cpu_has_feature(CPU_FTR_ARCH_31))) {
|
||||
record = 0;
|
||||
atomic64_inc(&event->lost_samples);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally record data if requested.
|
||||
*/
|
||||
|
||||
@@ -321,8 +321,10 @@ void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags,
|
||||
|
||||
sier = mfspr(SPRN_SIER);
|
||||
val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT;
|
||||
if (val != 1 && val != 2 && !(val == 7 && cpu_has_feature(CPU_FTR_ARCH_31)))
|
||||
if (val != 1 && val != 2 && !(val == 7 && cpu_has_feature(CPU_FTR_ARCH_31))) {
|
||||
dsrc->val = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
idx = (sier & ISA207_SIER_LDST_MASK) >> ISA207_SIER_LDST_SHIFT;
|
||||
sub_idx = (sier & ISA207_SIER_DATA_SRC_MASK) >> ISA207_SIER_DATA_SRC_SHIFT;
|
||||
|
||||
@@ -115,6 +115,7 @@ struct kernel_mapping {
|
||||
|
||||
extern struct kernel_mapping kernel_map;
|
||||
extern phys_addr_t phys_ram_base;
|
||||
extern unsigned long vmemmap_start_pfn;
|
||||
|
||||
#define is_kernel_mapping(x) \
|
||||
((x) >= kernel_map.virt_addr && (x) < (kernel_map.virt_addr + kernel_map.size))
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
* Define vmemmap for pfn_to_page & page_to_pfn calls. Needed if kernel
|
||||
* is configured with CONFIG_SPARSEMEM_VMEMMAP enabled.
|
||||
*/
|
||||
#define vmemmap ((struct page *)VMEMMAP_START - (phys_ram_base >> PAGE_SHIFT))
|
||||
#define vmemmap ((struct page *)VMEMMAP_START - vmemmap_start_pfn)
|
||||
|
||||
#define PCI_IO_SIZE SZ_16M
|
||||
#define PCI_IO_END VMEMMAP_START
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <linux/hugetlb.h>
|
||||
|
||||
#include <asm/fixmap.h>
|
||||
#include <asm/sparsemem.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/soc.h>
|
||||
@@ -52,6 +53,13 @@ EXPORT_SYMBOL(pgtable_l5_enabled);
|
||||
phys_addr_t phys_ram_base __ro_after_init;
|
||||
EXPORT_SYMBOL(phys_ram_base);
|
||||
|
||||
#ifdef CONFIG_SPARSEMEM_VMEMMAP
|
||||
#define VMEMMAP_ADDR_ALIGN (1ULL << SECTION_SIZE_BITS)
|
||||
|
||||
unsigned long vmemmap_start_pfn __ro_after_init;
|
||||
EXPORT_SYMBOL(vmemmap_start_pfn);
|
||||
#endif
|
||||
|
||||
unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]
|
||||
__page_aligned_bss;
|
||||
EXPORT_SYMBOL(empty_zero_page);
|
||||
@@ -210,8 +218,12 @@ static void __init setup_bootmem(void)
|
||||
memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start);
|
||||
|
||||
phys_ram_end = memblock_end_of_DRAM();
|
||||
if (!IS_ENABLED(CONFIG_XIP_KERNEL))
|
||||
if (!IS_ENABLED(CONFIG_XIP_KERNEL)) {
|
||||
phys_ram_base = memblock_start_of_DRAM();
|
||||
#ifdef CONFIG_SPARSEMEM_VMEMMAP
|
||||
vmemmap_start_pfn = round_down(phys_ram_base, VMEMMAP_ADDR_ALIGN) >> PAGE_SHIFT;
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Reserve physical address space that would be mapped to virtual
|
||||
* addresses greater than (void *)(-PAGE_SIZE) because:
|
||||
@@ -946,6 +958,9 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
|
||||
kernel_map.xiprom_sz = (uintptr_t)(&_exiprom) - (uintptr_t)(&_xiprom);
|
||||
|
||||
phys_ram_base = CONFIG_PHYS_RAM_BASE;
|
||||
#ifdef CONFIG_SPARSEMEM_VMEMMAP
|
||||
vmemmap_start_pfn = round_down(phys_ram_base, VMEMMAP_ADDR_ALIGN) >> PAGE_SHIFT;
|
||||
#endif
|
||||
kernel_map.phys_addr = (uintptr_t)CONFIG_PHYS_RAM_BASE;
|
||||
kernel_map.size = (uintptr_t)(&_end) - (uintptr_t)(&_start);
|
||||
|
||||
|
||||
@@ -155,5 +155,6 @@ MRPROPER_FILES += $(HOST_DIR)/include/generated
|
||||
archclean:
|
||||
@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
|
||||
-o -name '*.gcov' \) -type f -print | xargs rm -f
|
||||
$(Q)$(MAKE) -f $(srctree)/Makefile ARCH=$(HEADER_ARCH) clean
|
||||
|
||||
export HEADER_ARCH SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS DEV_NULL_PATH
|
||||
|
||||
@@ -68,6 +68,7 @@ void __init mem_init(void)
|
||||
map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
|
||||
memblock_free((void *)brk_end, uml_reserved - brk_end);
|
||||
uml_reserved = brk_end;
|
||||
min_low_pfn = PFN_UP(__pa(uml_reserved));
|
||||
|
||||
/* this will put all low memory onto the freelists */
|
||||
memblock_free_all();
|
||||
|
||||
@@ -2576,6 +2576,17 @@ config MITIGATION_SPECTRE_BHI
|
||||
indirect branches.
|
||||
See <file:Documentation/admin-guide/hw-vuln/spectre.rst>
|
||||
|
||||
config MITIGATION_ITS
|
||||
bool "Enable Indirect Target Selection mitigation"
|
||||
depends on CPU_SUP_INTEL && X86_64
|
||||
depends on RETPOLINE && RETHUNK
|
||||
default y
|
||||
help
|
||||
Enable Indirect Target Selection (ITS) mitigation. ITS is a bug in
|
||||
BPU on some Intel CPUs that may allow Spectre V2 style attacks. If
|
||||
disabled, mitigation cannot be enabled via cmdline.
|
||||
See <file:Documentation/admin-guide/hw-vuln/indirect-target-selection.rst>
|
||||
|
||||
endif
|
||||
|
||||
config ARCH_HAS_ADD_PAGES
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
# This script requires:
|
||||
# bash
|
||||
# syslinux
|
||||
# genisoimage
|
||||
# mtools (for fdimage* and hdimage)
|
||||
# edk2/OVMF (for hdimage)
|
||||
#
|
||||
@@ -251,7 +252,9 @@ geniso() {
|
||||
cp "$isolinux" "$ldlinux" "$tmp_dir"
|
||||
cp "$FBZIMAGE" "$tmp_dir"/linux
|
||||
echo default linux "$KCMDLINE" > "$tmp_dir"/isolinux.cfg
|
||||
cp "${FDINITRDS[@]}" "$tmp_dir"/
|
||||
if [ ${#FDINITRDS[@]} -gt 0 ]; then
|
||||
cp "${FDINITRDS[@]}" "$tmp_dir"/
|
||||
fi
|
||||
genisoimage -J -r -appid 'LINUX_BOOT' -input-charset=utf-8 \
|
||||
-quiet -o "$FIMAGE" -b isolinux.bin \
|
||||
-c boot.cat -no-emul-boot -boot-load-size 4 \
|
||||
|
||||
@@ -1559,7 +1559,9 @@ SYM_CODE_END(rewind_stack_and_make_dead)
|
||||
* ORC to unwind properly.
|
||||
*
|
||||
* The alignment is for performance and not for safety, and may be safely
|
||||
* refactored in the future if needed.
|
||||
* refactored in the future if needed. The .skips are for safety, to ensure
|
||||
* that all RETs are in the second half of a cacheline to mitigate Indirect
|
||||
* Target Selection, rather than taking the slowpath via its_return_thunk.
|
||||
*/
|
||||
SYM_FUNC_START(clear_bhb_loop)
|
||||
push %rbp
|
||||
@@ -1569,10 +1571,22 @@ SYM_FUNC_START(clear_bhb_loop)
|
||||
call 1f
|
||||
jmp 5f
|
||||
.align 64, 0xcc
|
||||
/*
|
||||
* Shift instructions so that the RET is in the upper half of the
|
||||
* cacheline and don't take the slowpath to its_return_thunk.
|
||||
*/
|
||||
.skip 32 - (.Lret1 - 1f), 0xcc
|
||||
ANNOTATE_INTRA_FUNCTION_CALL
|
||||
1: call 2f
|
||||
RET
|
||||
.Lret1: RET
|
||||
.align 64, 0xcc
|
||||
/*
|
||||
* As above shift instructions for RET at .Lret2 as well.
|
||||
*
|
||||
* This should be ideally be: .skip 32 - (.Lret2 - 2f), 0xcc
|
||||
* but some Clang versions (e.g. 18) don't like this.
|
||||
*/
|
||||
.skip 32 - 18, 0xcc
|
||||
2: movl $5, %eax
|
||||
3: jmp 4f
|
||||
nop
|
||||
@@ -1580,7 +1594,7 @@ SYM_FUNC_START(clear_bhb_loop)
|
||||
jnz 3b
|
||||
sub $1, %ecx
|
||||
jnz 1b
|
||||
RET
|
||||
.Lret2: RET
|
||||
5: lfence
|
||||
pop %rbp
|
||||
RET
|
||||
|
||||
@@ -1216,7 +1216,8 @@ static __init int perf_ibs_op_init(void)
|
||||
if (ibs_caps & IBS_CAPS_OPCNTEXT) {
|
||||
perf_ibs_op.max_period |= IBS_OP_MAX_CNT_EXT_MASK;
|
||||
perf_ibs_op.config_mask |= IBS_OP_MAX_CNT_EXT_MASK;
|
||||
perf_ibs_op.cnt_mask |= IBS_OP_MAX_CNT_EXT_MASK;
|
||||
perf_ibs_op.cnt_mask |= (IBS_OP_MAX_CNT_EXT_MASK |
|
||||
IBS_OP_CUR_CNT_EXT_MASK);
|
||||
}
|
||||
|
||||
if (ibs_caps & IBS_CAPS_ZEN4)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/stringify.h>
|
||||
#include <asm/asm.h>
|
||||
#include <asm/bug.h>
|
||||
|
||||
#define ALTINSTR_FLAG_INV (1 << 15)
|
||||
#define ALT_NOT(feat) ((feat) | ALTINSTR_FLAG_INV)
|
||||
@@ -81,6 +82,37 @@ extern void apply_ibt_endbr(s32 *start, s32 *end);
|
||||
|
||||
struct module;
|
||||
|
||||
#ifdef CONFIG_MITIGATION_ITS
|
||||
extern void its_init_mod(struct module *mod);
|
||||
extern void its_fini_mod(struct module *mod);
|
||||
extern void its_free_mod(struct module *mod);
|
||||
extern u8 *its_static_thunk(int reg);
|
||||
#else /* CONFIG_MITIGATION_ITS */
|
||||
static inline void its_init_mod(struct module *mod) { }
|
||||
static inline void its_fini_mod(struct module *mod) { }
|
||||
static inline void its_free_mod(struct module *mod) { }
|
||||
static inline u8 *its_static_thunk(int reg)
|
||||
{
|
||||
WARN_ONCE(1, "ITS not compiled in");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_RETHUNK) && defined(CONFIG_OBJTOOL)
|
||||
extern bool cpu_wants_rethunk(void);
|
||||
extern bool cpu_wants_rethunk_at(void *addr);
|
||||
#else
|
||||
static __always_inline bool cpu_wants_rethunk(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static __always_inline bool cpu_wants_rethunk_at(void *addr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
extern void alternatives_smp_module_add(struct module *mod, char *name,
|
||||
void *locks, void *locks_end,
|
||||
|
||||
@@ -445,6 +445,7 @@
|
||||
#define X86_FEATURE_BHI_CTRL (21*32+ 2) /* "" BHI_DIS_S HW control available */
|
||||
#define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* "" BHI_DIS_S HW control enabled */
|
||||
#define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* "" Clear branch history at vmexit using SW loop */
|
||||
#define X86_FEATURE_INDIRECT_THUNK_ITS (21*32 + 5) /* "" Use thunk for indirect branches in lower half of cacheline */
|
||||
|
||||
/*
|
||||
* BUG word(s)
|
||||
@@ -495,4 +496,6 @@
|
||||
#define X86_BUG_RFDS X86_BUG(1*32 + 2) /* CPU is vulnerable to Register File Data Sampling */
|
||||
#define X86_BUG_BHI X86_BUG(1*32 + 3) /* CPU is affected by Branch History Injection */
|
||||
#define X86_BUG_IBPB_NO_RET X86_BUG(1*32 + 4) /* "ibpb_no_ret" IBPB omits return target predictions */
|
||||
#define X86_BUG_ITS X86_BUG(1*32 + 5) /* CPU is affected by Indirect Target Selection */
|
||||
#define X86_BUG_ITS_NATIVE_ONLY X86_BUG(1*32 + 6) /* CPU is affected by ITS, VMX is not affected */
|
||||
#endif /* _ASM_X86_CPUFEATURES_H */
|
||||
|
||||
@@ -185,6 +185,14 @@
|
||||
* VERW clears CPU Register
|
||||
* File.
|
||||
*/
|
||||
#define ARCH_CAP_ITS_NO BIT_ULL(62) /*
|
||||
* Not susceptible to
|
||||
* Indirect Target Selection.
|
||||
* This bit is not set by
|
||||
* HW, but is synthesized by
|
||||
* VMMs for guests to know
|
||||
* their affected status.
|
||||
*/
|
||||
|
||||
#define ARCH_CAP_XAPIC_DISABLE BIT(21) /*
|
||||
* IA32_XAPIC_DISABLE_STATUS MSR
|
||||
|
||||
@@ -59,6 +59,8 @@ int __register_nmi_handler(unsigned int, struct nmiaction *);
|
||||
|
||||
void unregister_nmi_handler(unsigned int, const char *);
|
||||
|
||||
void set_emergency_nmi_handler(unsigned int type, nmi_handler_t handler);
|
||||
|
||||
void stop_nmi(void);
|
||||
void restart_nmi(void);
|
||||
void local_touch_nmi(void);
|
||||
|
||||
@@ -119,9 +119,8 @@
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Equivalent to -mindirect-branch-cs-prefix; emit the 5 byte jmp/call
|
||||
* to the retpoline thunk with a CS prefix when the register requires
|
||||
* a RAX prefix byte to encode. Also see apply_retpolines().
|
||||
* Emits a conditional CS prefix that is compatible with
|
||||
* -mindirect-branch-cs-prefix.
|
||||
*/
|
||||
.macro __CS_PREFIX reg:req
|
||||
.irp rs,r8,r9,r10,r11,r12,r13,r14,r15
|
||||
@@ -245,8 +244,12 @@
|
||||
_ASM_PTR " 999b\n\t" \
|
||||
".popsection\n\t"
|
||||
|
||||
#define ITS_THUNK_SIZE 64
|
||||
|
||||
typedef u8 retpoline_thunk_t[RETPOLINE_THUNK_SIZE];
|
||||
typedef u8 its_thunk_t[ITS_THUNK_SIZE];
|
||||
extern retpoline_thunk_t __x86_indirect_thunk_array[];
|
||||
extern its_thunk_t __x86_indirect_its_thunk_array[];
|
||||
|
||||
#ifdef CONFIG_RETHUNK
|
||||
extern void __x86_return_thunk(void);
|
||||
@@ -254,6 +257,12 @@ extern void __x86_return_thunk(void);
|
||||
static inline void __x86_return_thunk(void) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MITIGATION_ITS
|
||||
extern void its_return_thunk(void);
|
||||
#else
|
||||
static inline void its_return_thunk(void) {}
|
||||
#endif
|
||||
|
||||
extern void retbleed_return_thunk(void);
|
||||
extern void srso_return_thunk(void);
|
||||
extern void srso_alias_return_thunk(void);
|
||||
@@ -280,20 +289,23 @@ extern void (*x86_return_thunk)(void);
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
|
||||
/*
|
||||
* Emits a conditional CS prefix that is compatible with
|
||||
* -mindirect-branch-cs-prefix.
|
||||
*/
|
||||
#define __CS_PREFIX(reg) \
|
||||
".irp rs,r8,r9,r10,r11,r12,r13,r14,r15\n" \
|
||||
".ifc \\rs," reg "\n" \
|
||||
".byte 0x2e\n" \
|
||||
".endif\n" \
|
||||
".endr\n"
|
||||
|
||||
/*
|
||||
* Inline asm uses the %V modifier which is only in newer GCC
|
||||
* which is ensured when CONFIG_RETPOLINE is defined.
|
||||
*/
|
||||
# define CALL_NOSPEC \
|
||||
ALTERNATIVE_2( \
|
||||
ANNOTATE_RETPOLINE_SAFE \
|
||||
"call *%[thunk_target]\n", \
|
||||
"call __x86_indirect_thunk_%V[thunk_target]\n", \
|
||||
X86_FEATURE_RETPOLINE, \
|
||||
"lfence;\n" \
|
||||
ANNOTATE_RETPOLINE_SAFE \
|
||||
"call *%[thunk_target]\n", \
|
||||
X86_FEATURE_RETPOLINE_LFENCE)
|
||||
#define CALL_NOSPEC __CS_PREFIX("%V[thunk_target]") \
|
||||
"call __x86_indirect_thunk_%V[thunk_target]\n"
|
||||
|
||||
# define THUNK_TARGET(addr) [thunk_target] "r" (addr)
|
||||
|
||||
|
||||
@@ -456,6 +456,7 @@ struct pebs_xmm {
|
||||
*/
|
||||
#define IBS_OP_CUR_CNT (0xFFF80ULL<<32)
|
||||
#define IBS_OP_CUR_CNT_RAND (0x0007FULL<<32)
|
||||
#define IBS_OP_CUR_CNT_EXT_MASK (0x7FULL<<52)
|
||||
#define IBS_OP_CNT_CTL (1ULL<<19)
|
||||
#define IBS_OP_VAL (1ULL<<18)
|
||||
#define IBS_OP_ENABLE (1ULL<<17)
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include <linux/mmu_context.h>
|
||||
#include <linux/bsearch.h>
|
||||
#include <linux/sync_core.h>
|
||||
#include <linux/moduleloader.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <asm/text-patching.h>
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/sections.h>
|
||||
@@ -30,6 +32,8 @@
|
||||
#include <asm/fixmap.h>
|
||||
#include <asm/paravirt.h>
|
||||
#include <asm/asm-prototypes.h>
|
||||
#include <asm/cfi.h>
|
||||
#include <asm/set_memory.h>
|
||||
|
||||
int __read_mostly alternatives_patched;
|
||||
|
||||
@@ -396,6 +400,212 @@ static int emit_indirect(int op, int reg, u8 *bytes)
|
||||
return i;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MITIGATION_ITS
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
static struct module *its_mod;
|
||||
static void *its_page;
|
||||
static unsigned int its_offset;
|
||||
|
||||
/* Initialize a thunk with the "jmp *reg; int3" instructions. */
|
||||
static void *its_init_thunk(void *thunk, int reg)
|
||||
{
|
||||
u8 *bytes = thunk;
|
||||
int i = 0;
|
||||
|
||||
if (reg >= 8) {
|
||||
bytes[i++] = 0x41; /* REX.B prefix */
|
||||
reg -= 8;
|
||||
}
|
||||
bytes[i++] = 0xff;
|
||||
bytes[i++] = 0xe0 + reg; /* jmp *reg */
|
||||
bytes[i++] = 0xcc;
|
||||
|
||||
return thunk;
|
||||
}
|
||||
|
||||
void its_init_mod(struct module *mod)
|
||||
{
|
||||
if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS))
|
||||
return;
|
||||
|
||||
mutex_lock(&text_mutex);
|
||||
its_mod = mod;
|
||||
its_page = NULL;
|
||||
}
|
||||
|
||||
void its_fini_mod(struct module *mod)
|
||||
{
|
||||
if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS))
|
||||
return;
|
||||
|
||||
WARN_ON_ONCE(its_mod != mod);
|
||||
|
||||
its_mod = NULL;
|
||||
its_page = NULL;
|
||||
mutex_unlock(&text_mutex);
|
||||
|
||||
for (int i = 0; i < mod->its_num_pages; i++) {
|
||||
void *page = mod->its_page_array[i];
|
||||
set_memory_ro((unsigned long)page, 1);
|
||||
set_memory_x((unsigned long)page, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void its_free_mod(struct module *mod)
|
||||
{
|
||||
if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS))
|
||||
return;
|
||||
|
||||
for (int i = 0; i < mod->its_num_pages; i++) {
|
||||
void *page = mod->its_page_array[i];
|
||||
module_memfree(page);
|
||||
}
|
||||
kfree(mod->its_page_array);
|
||||
}
|
||||
|
||||
DEFINE_FREE(its_execmem, void *, if (_T) module_memfree(_T));
|
||||
|
||||
static void *its_alloc(void)
|
||||
{
|
||||
void *page __free(its_execmem) = module_alloc(PAGE_SIZE);
|
||||
|
||||
if (!page)
|
||||
return NULL;
|
||||
|
||||
if (its_mod) {
|
||||
void *tmp = krealloc(its_mod->its_page_array,
|
||||
(its_mod->its_num_pages+1) * sizeof(void *),
|
||||
GFP_KERNEL);
|
||||
if (!tmp)
|
||||
return NULL;
|
||||
|
||||
its_mod->its_page_array = tmp;
|
||||
its_mod->its_page_array[its_mod->its_num_pages++] = page;
|
||||
}
|
||||
|
||||
return no_free_ptr(page);
|
||||
}
|
||||
|
||||
static void *its_allocate_thunk(int reg)
|
||||
{
|
||||
int size = 3 + (reg / 8);
|
||||
void *thunk;
|
||||
|
||||
if (!its_page || (its_offset + size - 1) >= PAGE_SIZE) {
|
||||
its_page = its_alloc();
|
||||
if (!its_page) {
|
||||
pr_err("ITS page allocation failed\n");
|
||||
return NULL;
|
||||
}
|
||||
memset(its_page, INT3_INSN_OPCODE, PAGE_SIZE);
|
||||
its_offset = 32;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the indirect branch instruction will be in the lower half
|
||||
* of a cacheline, then update the offset to reach the upper half.
|
||||
*/
|
||||
if ((its_offset + size - 1) % 64 < 32)
|
||||
its_offset = ((its_offset - 1) | 0x3F) + 33;
|
||||
|
||||
thunk = its_page + its_offset;
|
||||
its_offset += size;
|
||||
|
||||
set_memory_rw((unsigned long)its_page, 1);
|
||||
thunk = its_init_thunk(thunk, reg);
|
||||
set_memory_ro((unsigned long)its_page, 1);
|
||||
set_memory_x((unsigned long)its_page, 1);
|
||||
|
||||
return thunk;
|
||||
}
|
||||
#else /* CONFIG_MODULES */
|
||||
|
||||
static void *its_allocate_thunk(int reg)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MODULES */
|
||||
|
||||
static int __emit_trampoline(void *addr, struct insn *insn, u8 *bytes,
|
||||
void *call_dest, void *jmp_dest)
|
||||
{
|
||||
u8 op = insn->opcode.bytes[0];
|
||||
int i = 0;
|
||||
|
||||
/*
|
||||
* Clang does 'weird' Jcc __x86_indirect_thunk_r11 conditional
|
||||
* tail-calls. Deal with them.
|
||||
*/
|
||||
if (is_jcc32(insn)) {
|
||||
bytes[i++] = op;
|
||||
op = insn->opcode.bytes[1];
|
||||
goto clang_jcc;
|
||||
}
|
||||
|
||||
if (insn->length == 6)
|
||||
bytes[i++] = 0x2e; /* CS-prefix */
|
||||
|
||||
switch (op) {
|
||||
case CALL_INSN_OPCODE:
|
||||
__text_gen_insn(bytes+i, op, addr+i,
|
||||
call_dest,
|
||||
CALL_INSN_SIZE);
|
||||
i += CALL_INSN_SIZE;
|
||||
break;
|
||||
|
||||
case JMP32_INSN_OPCODE:
|
||||
clang_jcc:
|
||||
__text_gen_insn(bytes+i, op, addr+i,
|
||||
jmp_dest,
|
||||
JMP32_INSN_SIZE);
|
||||
i += JMP32_INSN_SIZE;
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN(1, "%pS %px %*ph\n", addr, addr, 6, addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
WARN_ON_ONCE(i != insn->length);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int emit_its_trampoline(void *addr, struct insn *insn, int reg, u8 *bytes)
|
||||
{
|
||||
u8 *thunk = __x86_indirect_its_thunk_array[reg];
|
||||
u8 *tmp = its_allocate_thunk(reg);
|
||||
|
||||
if (tmp)
|
||||
thunk = tmp;
|
||||
|
||||
return __emit_trampoline(addr, insn, bytes, thunk, thunk);
|
||||
}
|
||||
|
||||
/* Check if an indirect branch is at ITS-unsafe address */
|
||||
static bool cpu_wants_indirect_its_thunk_at(unsigned long addr, int reg)
|
||||
{
|
||||
if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS))
|
||||
return false;
|
||||
|
||||
/* Indirect branch opcode is 2 or 3 bytes depending on reg */
|
||||
addr += 1 + reg / 8;
|
||||
|
||||
/* Lower-half of the cacheline? */
|
||||
return !(addr & 0x20);
|
||||
}
|
||||
|
||||
u8 *its_static_thunk(int reg)
|
||||
{
|
||||
u8 *thunk = __x86_indirect_its_thunk_array[reg];
|
||||
|
||||
return thunk;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Rewrite the compiler generated retpoline thunk calls.
|
||||
*
|
||||
@@ -466,6 +676,15 @@ static int patch_retpoline(void *addr, struct insn *insn, u8 *bytes)
|
||||
bytes[i++] = 0xe8; /* LFENCE */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MITIGATION_ITS
|
||||
/*
|
||||
* Check if the address of last byte of emitted-indirect is in
|
||||
* lower-half of the cacheline. Such branches need ITS mitigation.
|
||||
*/
|
||||
if (cpu_wants_indirect_its_thunk_at((unsigned long)addr + i, reg))
|
||||
return emit_its_trampoline(addr, insn, reg, bytes);
|
||||
#endif
|
||||
|
||||
ret = emit_indirect(op, reg, bytes + i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -537,6 +756,21 @@ void __init_or_module noinline apply_retpolines(s32 *start, s32 *end)
|
||||
|
||||
#ifdef CONFIG_RETHUNK
|
||||
|
||||
bool cpu_wants_rethunk(void)
|
||||
{
|
||||
return cpu_feature_enabled(X86_FEATURE_RETHUNK);
|
||||
}
|
||||
|
||||
bool cpu_wants_rethunk_at(void *addr)
|
||||
{
|
||||
if (!cpu_feature_enabled(X86_FEATURE_RETHUNK))
|
||||
return false;
|
||||
if (x86_return_thunk != its_return_thunk)
|
||||
return true;
|
||||
|
||||
return !((unsigned long)addr & 0x20);
|
||||
}
|
||||
|
||||
/*
|
||||
* Rewrite the compiler generated return thunk tail-calls.
|
||||
*
|
||||
@@ -552,13 +786,12 @@ static int patch_return(void *addr, struct insn *insn, u8 *bytes)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (cpu_feature_enabled(X86_FEATURE_RETHUNK)) {
|
||||
if (x86_return_thunk == __x86_return_thunk)
|
||||
return -1;
|
||||
|
||||
/* Patch the custom return thunks... */
|
||||
if (cpu_wants_rethunk_at(addr)) {
|
||||
i = JMP32_INSN_SIZE;
|
||||
__text_gen_insn(bytes, JMP32_INSN_OPCODE, addr, x86_return_thunk, i);
|
||||
} else {
|
||||
/* ... or patch them out if not needed. */
|
||||
bytes[i++] = RET_INSN_OPCODE;
|
||||
}
|
||||
|
||||
@@ -914,6 +1147,8 @@ static noinline void __init int3_selftest(void)
|
||||
|
||||
void __init alternative_instructions(void)
|
||||
{
|
||||
u64 ibt;
|
||||
|
||||
int3_selftest();
|
||||
|
||||
/*
|
||||
@@ -951,6 +1186,9 @@ void __init alternative_instructions(void)
|
||||
*/
|
||||
paravirt_set_cap();
|
||||
|
||||
/* Keep CET-IBT disabled until caller/callee are patched */
|
||||
ibt = ibt_save();
|
||||
|
||||
/*
|
||||
* First patch paravirt functions, such that we overwrite the indirect
|
||||
* call with the direct call.
|
||||
@@ -972,6 +1210,8 @@ void __init alternative_instructions(void)
|
||||
|
||||
apply_ibt_endbr(__ibt_endbr_seal, __ibt_endbr_seal_end);
|
||||
|
||||
ibt_restore(ibt);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Patch to UP if other cpus not imminent. */
|
||||
if (!noreplace_smp && (num_present_cpus() == 1 || setup_max_cpus <= 1)) {
|
||||
|
||||
@@ -48,6 +48,7 @@ static void __init srbds_select_mitigation(void);
|
||||
static void __init l1d_flush_select_mitigation(void);
|
||||
static void __init gds_select_mitigation(void);
|
||||
static void __init srso_select_mitigation(void);
|
||||
static void __init its_select_mitigation(void);
|
||||
|
||||
/* The base value of the SPEC_CTRL MSR without task-specific bits set */
|
||||
u64 x86_spec_ctrl_base;
|
||||
@@ -66,6 +67,14 @@ static DEFINE_MUTEX(spec_ctrl_mutex);
|
||||
|
||||
void (*x86_return_thunk)(void) __ro_after_init = &__x86_return_thunk;
|
||||
|
||||
static void __init set_return_thunk(void *thunk)
|
||||
{
|
||||
if (x86_return_thunk != __x86_return_thunk)
|
||||
pr_warn("x86/bugs: return thunk changed\n");
|
||||
|
||||
x86_return_thunk = thunk;
|
||||
}
|
||||
|
||||
/* Update SPEC_CTRL MSR and its cached copy unconditionally */
|
||||
static void update_spec_ctrl(u64 val)
|
||||
{
|
||||
@@ -174,6 +183,7 @@ void __init cpu_select_mitigations(void)
|
||||
*/
|
||||
srso_select_mitigation();
|
||||
gds_select_mitigation();
|
||||
its_select_mitigation();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1081,7 +1091,7 @@ do_cmd_auto:
|
||||
setup_force_cpu_cap(X86_FEATURE_UNRET);
|
||||
|
||||
if (IS_ENABLED(CONFIG_RETHUNK))
|
||||
x86_return_thunk = retbleed_return_thunk;
|
||||
set_return_thunk(retbleed_return_thunk);
|
||||
|
||||
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
|
||||
boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
|
||||
@@ -1142,6 +1152,116 @@ do_cmd_auto:
|
||||
pr_info("%s\n", retbleed_strings[retbleed_mitigation]);
|
||||
}
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) "ITS: " fmt
|
||||
|
||||
enum its_mitigation_cmd {
|
||||
ITS_CMD_OFF,
|
||||
ITS_CMD_ON,
|
||||
ITS_CMD_VMEXIT,
|
||||
};
|
||||
|
||||
enum its_mitigation {
|
||||
ITS_MITIGATION_OFF,
|
||||
ITS_MITIGATION_VMEXIT_ONLY,
|
||||
ITS_MITIGATION_ALIGNED_THUNKS,
|
||||
};
|
||||
|
||||
static const char * const its_strings[] = {
|
||||
[ITS_MITIGATION_OFF] = "Vulnerable",
|
||||
[ITS_MITIGATION_VMEXIT_ONLY] = "Mitigation: Vulnerable, KVM: Not affected",
|
||||
[ITS_MITIGATION_ALIGNED_THUNKS] = "Mitigation: Aligned branch/return thunks",
|
||||
};
|
||||
|
||||
static enum its_mitigation its_mitigation __ro_after_init = ITS_MITIGATION_ALIGNED_THUNKS;
|
||||
|
||||
static enum its_mitigation_cmd its_cmd __ro_after_init =
|
||||
IS_ENABLED(CONFIG_MITIGATION_ITS) ? ITS_CMD_ON : ITS_CMD_OFF;
|
||||
|
||||
static int __init its_parse_cmdline(char *str)
|
||||
{
|
||||
if (!str)
|
||||
return -EINVAL;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_MITIGATION_ITS)) {
|
||||
pr_err("Mitigation disabled at compile time, ignoring option (%s)", str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(str, "off")) {
|
||||
its_cmd = ITS_CMD_OFF;
|
||||
} else if (!strcmp(str, "on")) {
|
||||
its_cmd = ITS_CMD_ON;
|
||||
} else if (!strcmp(str, "force")) {
|
||||
its_cmd = ITS_CMD_ON;
|
||||
setup_force_cpu_bug(X86_BUG_ITS);
|
||||
} else if (!strcmp(str, "vmexit")) {
|
||||
its_cmd = ITS_CMD_VMEXIT;
|
||||
} else {
|
||||
pr_err("Ignoring unknown indirect_target_selection option (%s).", str);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_param("indirect_target_selection", its_parse_cmdline);
|
||||
|
||||
static void __init its_select_mitigation(void)
|
||||
{
|
||||
enum its_mitigation_cmd cmd = its_cmd;
|
||||
|
||||
if (!boot_cpu_has_bug(X86_BUG_ITS) || cpu_mitigations_off()) {
|
||||
its_mitigation = ITS_MITIGATION_OFF;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Exit early to avoid irrelevant warnings */
|
||||
if (cmd == ITS_CMD_OFF) {
|
||||
its_mitigation = ITS_MITIGATION_OFF;
|
||||
goto out;
|
||||
}
|
||||
if (spectre_v2_enabled == SPECTRE_V2_NONE) {
|
||||
pr_err("WARNING: Spectre-v2 mitigation is off, disabling ITS\n");
|
||||
its_mitigation = ITS_MITIGATION_OFF;
|
||||
goto out;
|
||||
}
|
||||
if (!IS_ENABLED(CONFIG_RETPOLINE) || !IS_ENABLED(CONFIG_RETHUNK)) {
|
||||
pr_err("WARNING: ITS mitigation depends on retpoline and rethunk support\n");
|
||||
its_mitigation = ITS_MITIGATION_OFF;
|
||||
goto out;
|
||||
}
|
||||
if (IS_ENABLED(CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B)) {
|
||||
pr_err("WARNING: ITS mitigation is not compatible with CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B\n");
|
||||
its_mitigation = ITS_MITIGATION_OFF;
|
||||
goto out;
|
||||
}
|
||||
if (boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE)) {
|
||||
pr_err("WARNING: ITS mitigation is not compatible with lfence mitigation\n");
|
||||
its_mitigation = ITS_MITIGATION_OFF;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case ITS_CMD_OFF:
|
||||
its_mitigation = ITS_MITIGATION_OFF;
|
||||
break;
|
||||
case ITS_CMD_VMEXIT:
|
||||
if (boot_cpu_has_bug(X86_BUG_ITS_NATIVE_ONLY)) {
|
||||
its_mitigation = ITS_MITIGATION_VMEXIT_ONLY;
|
||||
goto out;
|
||||
}
|
||||
fallthrough;
|
||||
case ITS_CMD_ON:
|
||||
its_mitigation = ITS_MITIGATION_ALIGNED_THUNKS;
|
||||
if (!boot_cpu_has(X86_FEATURE_RETPOLINE))
|
||||
setup_force_cpu_cap(X86_FEATURE_INDIRECT_THUNK_ITS);
|
||||
setup_force_cpu_cap(X86_FEATURE_RETHUNK);
|
||||
set_return_thunk(its_return_thunk);
|
||||
break;
|
||||
}
|
||||
out:
|
||||
pr_info("%s\n", its_strings[its_mitigation]);
|
||||
}
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) "Spectre V2 : " fmt
|
||||
|
||||
@@ -1262,9 +1382,13 @@ static __ro_after_init enum spectre_v2_mitigation_cmd spectre_v2_cmd;
|
||||
static enum spectre_v2_user_cmd __init
|
||||
spectre_v2_parse_user_cmdline(void)
|
||||
{
|
||||
enum spectre_v2_user_cmd mode;
|
||||
char arg[20];
|
||||
int ret, i;
|
||||
|
||||
mode = IS_ENABLED(CONFIG_MITIGATION_SPECTRE_V2) ?
|
||||
SPECTRE_V2_USER_CMD_AUTO : SPECTRE_V2_USER_CMD_NONE;
|
||||
|
||||
switch (spectre_v2_cmd) {
|
||||
case SPECTRE_V2_CMD_NONE:
|
||||
return SPECTRE_V2_USER_CMD_NONE;
|
||||
@@ -1277,7 +1401,7 @@ spectre_v2_parse_user_cmdline(void)
|
||||
ret = cmdline_find_option(boot_command_line, "spectre_v2_user",
|
||||
arg, sizeof(arg));
|
||||
if (ret < 0)
|
||||
return SPECTRE_V2_USER_CMD_AUTO;
|
||||
return mode;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(v2_user_options); i++) {
|
||||
if (match_option(arg, ret, v2_user_options[i].option)) {
|
||||
@@ -1287,8 +1411,8 @@ spectre_v2_parse_user_cmdline(void)
|
||||
}
|
||||
}
|
||||
|
||||
pr_err("Unknown user space protection option (%s). Switching to AUTO select\n", arg);
|
||||
return SPECTRE_V2_USER_CMD_AUTO;
|
||||
pr_err("Unknown user space protection option (%s). Switching to default\n", arg);
|
||||
return mode;
|
||||
}
|
||||
|
||||
static inline bool spectre_v2_in_eibrs_mode(enum spectre_v2_mitigation mode)
|
||||
@@ -1656,10 +1780,11 @@ static void __init bhi_select_mitigation(void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (spec_ctrl_bhi_dis())
|
||||
if (!IS_ENABLED(CONFIG_X86_64))
|
||||
return;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_X86_64))
|
||||
/* Mitigate in hardware if supported */
|
||||
if (spec_ctrl_bhi_dis())
|
||||
return;
|
||||
|
||||
/* Mitigate KVM by default */
|
||||
@@ -2591,10 +2716,10 @@ static void __init srso_select_mitigation(void)
|
||||
|
||||
if (boot_cpu_data.x86 == 0x19) {
|
||||
setup_force_cpu_cap(X86_FEATURE_SRSO_ALIAS);
|
||||
x86_return_thunk = srso_alias_return_thunk;
|
||||
set_return_thunk(srso_alias_return_thunk);
|
||||
} else {
|
||||
setup_force_cpu_cap(X86_FEATURE_SRSO);
|
||||
x86_return_thunk = srso_return_thunk;
|
||||
set_return_thunk(srso_return_thunk);
|
||||
}
|
||||
srso_mitigation = SRSO_MITIGATION_SAFE_RET;
|
||||
} else {
|
||||
@@ -2774,6 +2899,11 @@ static ssize_t rfds_show_state(char *buf)
|
||||
return sysfs_emit(buf, "%s\n", rfds_strings[rfds_mitigation]);
|
||||
}
|
||||
|
||||
static ssize_t its_show_state(char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "%s\n", its_strings[its_mitigation]);
|
||||
}
|
||||
|
||||
static char *stibp_state(void)
|
||||
{
|
||||
if (spectre_v2_in_eibrs_mode(spectre_v2_enabled) &&
|
||||
@@ -2958,6 +3088,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
|
||||
case X86_BUG_RFDS:
|
||||
return rfds_show_state(buf);
|
||||
|
||||
case X86_BUG_ITS:
|
||||
return its_show_state(buf);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -3037,4 +3170,9 @@ ssize_t cpu_show_reg_file_data_sampling(struct device *dev, struct device_attrib
|
||||
{
|
||||
return cpu_show_common(dev, attr, buf, X86_BUG_RFDS);
|
||||
}
|
||||
|
||||
ssize_t cpu_show_indirect_target_selection(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return cpu_show_common(dev, attr, buf, X86_BUG_ITS);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1251,6 +1251,10 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
|
||||
#define GDS BIT(6)
|
||||
/* CPU is affected by Register File Data Sampling */
|
||||
#define RFDS BIT(7)
|
||||
/* CPU is affected by Indirect Target Selection */
|
||||
#define ITS BIT(8)
|
||||
/* CPU is affected by Indirect Target Selection, but guest-host isolation is not affected */
|
||||
#define ITS_NATIVE_ONLY BIT(9)
|
||||
|
||||
static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
|
||||
VULNBL_INTEL_STEPPINGS(IVYBRIDGE, X86_STEPPING_ANY, SRBDS),
|
||||
@@ -1262,22 +1266,25 @@ static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
|
||||
VULNBL_INTEL_STEPPINGS(BROADWELL_G, X86_STEPPING_ANY, SRBDS),
|
||||
VULNBL_INTEL_STEPPINGS(BROADWELL_X, X86_STEPPING_ANY, MMIO),
|
||||
VULNBL_INTEL_STEPPINGS(BROADWELL, X86_STEPPING_ANY, SRBDS),
|
||||
VULNBL_INTEL_STEPPINGS(SKYLAKE_X, X86_STEPPING_ANY, MMIO | RETBLEED | GDS),
|
||||
VULNBL_INTEL_STEPPINGS(SKYLAKE_X, X86_STEPPINGS(0x0, 0x5), MMIO | RETBLEED | GDS),
|
||||
VULNBL_INTEL_STEPPINGS(SKYLAKE_X, X86_STEPPING_ANY, MMIO | RETBLEED | GDS | ITS),
|
||||
VULNBL_INTEL_STEPPINGS(SKYLAKE_L, X86_STEPPING_ANY, MMIO | RETBLEED | GDS | SRBDS),
|
||||
VULNBL_INTEL_STEPPINGS(SKYLAKE, X86_STEPPING_ANY, MMIO | RETBLEED | GDS | SRBDS),
|
||||
VULNBL_INTEL_STEPPINGS(KABYLAKE_L, X86_STEPPING_ANY, MMIO | RETBLEED | GDS | SRBDS),
|
||||
VULNBL_INTEL_STEPPINGS(KABYLAKE, X86_STEPPING_ANY, MMIO | RETBLEED | GDS | SRBDS),
|
||||
VULNBL_INTEL_STEPPINGS(KABYLAKE_L, X86_STEPPINGS(0x0, 0xb), MMIO | RETBLEED | GDS | SRBDS),
|
||||
VULNBL_INTEL_STEPPINGS(KABYLAKE_L, X86_STEPPING_ANY, MMIO | RETBLEED | GDS | SRBDS | ITS),
|
||||
VULNBL_INTEL_STEPPINGS(KABYLAKE, X86_STEPPINGS(0x0, 0xc), MMIO | RETBLEED | GDS | SRBDS),
|
||||
VULNBL_INTEL_STEPPINGS(KABYLAKE, X86_STEPPING_ANY, MMIO | RETBLEED | GDS | SRBDS | ITS),
|
||||
VULNBL_INTEL_STEPPINGS(CANNONLAKE_L, X86_STEPPING_ANY, RETBLEED),
|
||||
VULNBL_INTEL_STEPPINGS(ICELAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS),
|
||||
VULNBL_INTEL_STEPPINGS(ICELAKE_D, X86_STEPPING_ANY, MMIO | GDS),
|
||||
VULNBL_INTEL_STEPPINGS(ICELAKE_X, X86_STEPPING_ANY, MMIO | GDS),
|
||||
VULNBL_INTEL_STEPPINGS(COMETLAKE, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS),
|
||||
VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPINGS(0x0, 0x0), MMIO | RETBLEED),
|
||||
VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS),
|
||||
VULNBL_INTEL_STEPPINGS(TIGERLAKE_L, X86_STEPPING_ANY, GDS),
|
||||
VULNBL_INTEL_STEPPINGS(TIGERLAKE, X86_STEPPING_ANY, GDS),
|
||||
VULNBL_INTEL_STEPPINGS(ICELAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS | ITS | ITS_NATIVE_ONLY),
|
||||
VULNBL_INTEL_STEPPINGS(ICELAKE_D, X86_STEPPING_ANY, MMIO | GDS | ITS | ITS_NATIVE_ONLY),
|
||||
VULNBL_INTEL_STEPPINGS(ICELAKE_X, X86_STEPPING_ANY, MMIO | GDS | ITS | ITS_NATIVE_ONLY),
|
||||
VULNBL_INTEL_STEPPINGS(COMETLAKE, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS | ITS),
|
||||
VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPINGS(0x0, 0x0), MMIO | RETBLEED | ITS),
|
||||
VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS | ITS),
|
||||
VULNBL_INTEL_STEPPINGS(TIGERLAKE_L, X86_STEPPING_ANY, GDS | ITS | ITS_NATIVE_ONLY),
|
||||
VULNBL_INTEL_STEPPINGS(TIGERLAKE, X86_STEPPING_ANY, GDS | ITS | ITS_NATIVE_ONLY),
|
||||
VULNBL_INTEL_STEPPINGS(LAKEFIELD, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED),
|
||||
VULNBL_INTEL_STEPPINGS(ROCKETLAKE, X86_STEPPING_ANY, MMIO | RETBLEED | GDS),
|
||||
VULNBL_INTEL_STEPPINGS(ROCKETLAKE, X86_STEPPING_ANY, MMIO | RETBLEED | GDS | ITS | ITS_NATIVE_ONLY),
|
||||
VULNBL_INTEL_STEPPINGS(ALDERLAKE, X86_STEPPING_ANY, RFDS),
|
||||
VULNBL_INTEL_STEPPINGS(ALDERLAKE_L, X86_STEPPING_ANY, RFDS),
|
||||
VULNBL_INTEL_STEPPINGS(RAPTORLAKE, X86_STEPPING_ANY, RFDS),
|
||||
@@ -1341,6 +1348,32 @@ static bool __init vulnerable_to_rfds(u64 x86_arch_cap_msr)
|
||||
return cpu_matches(cpu_vuln_blacklist, RFDS);
|
||||
}
|
||||
|
||||
static bool __init vulnerable_to_its(u64 x86_arch_cap_msr)
|
||||
{
|
||||
/* The "immunity" bit trumps everything else: */
|
||||
if (x86_arch_cap_msr & ARCH_CAP_ITS_NO)
|
||||
return false;
|
||||
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
|
||||
return false;
|
||||
|
||||
/* None of the affected CPUs have BHI_CTRL */
|
||||
if (boot_cpu_has(X86_FEATURE_BHI_CTRL))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If a VMM did not expose ITS_NO, assume that a guest could
|
||||
* be running on a vulnerable hardware or may migrate to such
|
||||
* hardware.
|
||||
*/
|
||||
if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
|
||||
return true;
|
||||
|
||||
if (cpu_matches(cpu_vuln_blacklist, ITS))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u64 x86_arch_cap_msr = x86_read_arch_cap_msr();
|
||||
@@ -1455,9 +1488,12 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||
if (vulnerable_to_rfds(x86_arch_cap_msr))
|
||||
setup_force_cpu_bug(X86_BUG_RFDS);
|
||||
|
||||
/* When virtualized, eIBRS could be hidden, assume vulnerable */
|
||||
if (!(x86_arch_cap_msr & ARCH_CAP_BHI_NO) &&
|
||||
!cpu_matches(cpu_vuln_whitelist, NO_BHI) &&
|
||||
/*
|
||||
* Intel parts with eIBRS are vulnerable to BHI attacks. Parts with
|
||||
* BHI_NO still need to use the BHI mitigation to prevent Intra-mode
|
||||
* attacks. When virtualized, eIBRS could be hidden, assume vulnerable.
|
||||
*/
|
||||
if (!cpu_matches(cpu_vuln_whitelist, NO_BHI) &&
|
||||
(boot_cpu_has(X86_FEATURE_IBRS_ENHANCED) ||
|
||||
boot_cpu_has(X86_FEATURE_HYPERVISOR)))
|
||||
setup_force_cpu_bug(X86_BUG_BHI);
|
||||
@@ -1465,6 +1501,12 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||
if (cpu_has(c, X86_FEATURE_AMD_IBPB) && !cpu_has(c, X86_FEATURE_AMD_IBPB_RET))
|
||||
setup_force_cpu_bug(X86_BUG_IBPB_NO_RET);
|
||||
|
||||
if (vulnerable_to_its(x86_arch_cap_msr)) {
|
||||
setup_force_cpu_bug(X86_BUG_ITS);
|
||||
if (cpu_matches(cpu_vuln_blacklist, ITS_NATIVE_ONLY))
|
||||
setup_force_cpu_bug(X86_BUG_ITS_NATIVE_ONLY);
|
||||
}
|
||||
|
||||
if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
|
||||
return;
|
||||
|
||||
|
||||
@@ -360,7 +360,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
|
||||
goto fail;
|
||||
|
||||
ip = trampoline + size;
|
||||
if (cpu_feature_enabled(X86_FEATURE_RETHUNK))
|
||||
if (cpu_wants_rethunk_at(ip))
|
||||
__text_gen_insn(ip, JMP32_INSN_OPCODE, ip, x86_return_thunk, JMP32_INSN_SIZE);
|
||||
else
|
||||
memcpy(ip, retq, sizeof(retq));
|
||||
@@ -415,8 +415,6 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
|
||||
/* ALLOC_TRAMP flags lets us know we created it */
|
||||
ops->flags |= FTRACE_OPS_FL_ALLOC_TRAMP;
|
||||
|
||||
set_vm_flush_reset_perms(trampoline);
|
||||
|
||||
if (likely(system_state != SYSTEM_BOOTING))
|
||||
set_memory_ro((unsigned long)trampoline, npages);
|
||||
set_memory_x((unsigned long)trampoline, npages);
|
||||
|
||||
@@ -427,7 +427,6 @@ void *alloc_insn_page(void)
|
||||
if (!page)
|
||||
return NULL;
|
||||
|
||||
set_vm_flush_reset_perms(page);
|
||||
/*
|
||||
* First make the page read-only, and only then make it executable to
|
||||
* prevent it from being W+X in between.
|
||||
|
||||
@@ -74,10 +74,11 @@ void *module_alloc(unsigned long size)
|
||||
return NULL;
|
||||
|
||||
p = __vmalloc_node_range(size, MODULE_ALIGN,
|
||||
MODULES_VADDR + get_module_load_offset(),
|
||||
MODULES_END, gfp_mask,
|
||||
PAGE_KERNEL, VM_DEFER_KMEMLEAK, NUMA_NO_NODE,
|
||||
__builtin_return_address(0));
|
||||
MODULES_VADDR + get_module_load_offset(),
|
||||
MODULES_END, gfp_mask, PAGE_KERNEL,
|
||||
VM_FLUSH_RESET_PERMS | VM_DEFER_KMEMLEAK,
|
||||
NUMA_NO_NODE, __builtin_return_address(0));
|
||||
|
||||
if (p && (kasan_alloc_module_shadow(p, size, gfp_mask) < 0)) {
|
||||
vfree(p);
|
||||
return NULL;
|
||||
@@ -285,10 +286,16 @@ int module_finalize(const Elf_Ehdr *hdr,
|
||||
void *pseg = (void *)para->sh_addr;
|
||||
apply_paravirt(pseg, pseg + para->sh_size);
|
||||
}
|
||||
|
||||
its_init_mod(me);
|
||||
|
||||
if (retpolines) {
|
||||
void *rseg = (void *)retpolines->sh_addr;
|
||||
apply_retpolines(rseg, rseg + retpolines->sh_size);
|
||||
}
|
||||
|
||||
its_fini_mod(me);
|
||||
|
||||
if (returns) {
|
||||
void *rseg = (void *)returns->sh_addr;
|
||||
apply_returns(rseg, rseg + returns->sh_size);
|
||||
@@ -320,4 +327,5 @@ int module_finalize(const Elf_Ehdr *hdr,
|
||||
void module_arch_cleanup(struct module *mod)
|
||||
{
|
||||
alternatives_smp_module_del(mod);
|
||||
its_free_mod(mod);
|
||||
}
|
||||
|
||||
@@ -38,8 +38,12 @@
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/nmi.h>
|
||||
|
||||
/*
|
||||
* An emergency handler can be set in any context including NMI
|
||||
*/
|
||||
struct nmi_desc {
|
||||
raw_spinlock_t lock;
|
||||
nmi_handler_t emerg_handler;
|
||||
struct list_head head;
|
||||
};
|
||||
|
||||
@@ -121,9 +125,22 @@ static void nmi_check_duration(struct nmiaction *action, u64 duration)
|
||||
static int nmi_handle(unsigned int type, struct pt_regs *regs)
|
||||
{
|
||||
struct nmi_desc *desc = nmi_to_desc(type);
|
||||
nmi_handler_t ehandler;
|
||||
struct nmiaction *a;
|
||||
int handled=0;
|
||||
|
||||
/*
|
||||
* Call the emergency handler, if set
|
||||
*
|
||||
* In the case of crash_nmi_callback() emergency handler, it will
|
||||
* return in the case of the crashing CPU to enable it to complete
|
||||
* other necessary crashing actions ASAP. Other handlers in the
|
||||
* linked list won't need to be run.
|
||||
*/
|
||||
ehandler = desc->emerg_handler;
|
||||
if (ehandler)
|
||||
return ehandler(type, regs);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
/*
|
||||
@@ -213,6 +230,31 @@ void unregister_nmi_handler(unsigned int type, const char *name)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(unregister_nmi_handler);
|
||||
|
||||
/**
|
||||
* set_emergency_nmi_handler - Set emergency handler
|
||||
* @type: NMI type
|
||||
* @handler: the emergency handler to be stored
|
||||
*
|
||||
* Set an emergency NMI handler which, if set, will preempt all the other
|
||||
* handlers in the linked list. If a NULL handler is passed in, it will clear
|
||||
* it. It is expected that concurrent calls to this function will not happen
|
||||
* or the system is screwed beyond repair.
|
||||
*/
|
||||
void set_emergency_nmi_handler(unsigned int type, nmi_handler_t handler)
|
||||
{
|
||||
struct nmi_desc *desc = nmi_to_desc(type);
|
||||
|
||||
if (WARN_ON_ONCE(desc->emerg_handler == handler))
|
||||
return;
|
||||
desc->emerg_handler = handler;
|
||||
|
||||
/*
|
||||
* Ensure the emergency handler is visible to other CPUs before
|
||||
* function return
|
||||
*/
|
||||
smp_wmb();
|
||||
}
|
||||
|
||||
static void
|
||||
pci_serr_error(unsigned char reason, struct pt_regs *regs)
|
||||
{
|
||||
|
||||
@@ -896,15 +896,11 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback)
|
||||
shootdown_callback = callback;
|
||||
|
||||
atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
|
||||
/* Would it be better to replace the trap vector here? */
|
||||
if (register_nmi_handler(NMI_LOCAL, crash_nmi_callback,
|
||||
NMI_FLAG_FIRST, "crash"))
|
||||
return; /* Return what? */
|
||||
|
||||
/*
|
||||
* Ensure the new callback function is set before sending
|
||||
* out the NMI
|
||||
* Set emergency handler to preempt other handlers.
|
||||
*/
|
||||
wmb();
|
||||
set_emergency_nmi_handler(NMI_LOCAL, crash_nmi_callback);
|
||||
|
||||
apic_send_IPI_allbutself(NMI_VECTOR);
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ static void __ref __static_call_transform(void *insn, enum insn_type type,
|
||||
break;
|
||||
|
||||
case RET:
|
||||
if (cpu_feature_enabled(X86_FEATURE_RETHUNK))
|
||||
if (cpu_wants_rethunk_at(insn))
|
||||
code = text_gen_insn(JMP32_INSN_OPCODE, insn, x86_return_thunk);
|
||||
else
|
||||
code = &retinsn;
|
||||
|
||||
@@ -528,6 +528,16 @@ INIT_PER_CPU(irq_stack_backing_store);
|
||||
"SRSO function pair won't alias");
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MITIGATION_ITS) && !defined(CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B)
|
||||
. = ASSERT(__x86_indirect_its_thunk_rax & 0x20, "__x86_indirect_thunk_rax not in second half of cacheline");
|
||||
. = ASSERT(((__x86_indirect_its_thunk_rcx - __x86_indirect_its_thunk_rax) % 64) == 0, "Indirect thunks are not cacheline apart");
|
||||
. = ASSERT(__x86_indirect_its_thunk_array == __x86_indirect_its_thunk_rax, "Gap in ITS thunk array");
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MITIGATION_ITS) && !defined(CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B)
|
||||
. = ASSERT(its_return_thunk & 0x20, "its_return_thunk not in second half of cacheline");
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_X86_64 */
|
||||
|
||||
#ifdef CONFIG_KEXEC_CORE
|
||||
|
||||
@@ -1614,7 +1614,7 @@ static unsigned int num_msr_based_features;
|
||||
ARCH_CAP_PSCHANGE_MC_NO | ARCH_CAP_TSX_CTRL_MSR | ARCH_CAP_TAA_NO | \
|
||||
ARCH_CAP_SBDR_SSDP_NO | ARCH_CAP_FBSDP_NO | ARCH_CAP_PSDP_NO | \
|
||||
ARCH_CAP_FB_CLEAR | ARCH_CAP_RRSBA | ARCH_CAP_PBRSB_NO | ARCH_CAP_GDS_NO | \
|
||||
ARCH_CAP_RFDS_NO | ARCH_CAP_RFDS_CLEAR | ARCH_CAP_BHI_NO)
|
||||
ARCH_CAP_RFDS_NO | ARCH_CAP_RFDS_CLEAR | ARCH_CAP_BHI_NO | ARCH_CAP_ITS_NO)
|
||||
|
||||
static u64 kvm_get_arch_capabilities(void)
|
||||
{
|
||||
@@ -1653,6 +1653,8 @@ static u64 kvm_get_arch_capabilities(void)
|
||||
data |= ARCH_CAP_MDS_NO;
|
||||
if (!boot_cpu_has_bug(X86_BUG_RFDS))
|
||||
data |= ARCH_CAP_RFDS_NO;
|
||||
if (!boot_cpu_has_bug(X86_BUG_ITS))
|
||||
data |= ARCH_CAP_ITS_NO;
|
||||
|
||||
if (!boot_cpu_has(X86_FEATURE_RTM)) {
|
||||
/*
|
||||
|
||||
@@ -258,6 +258,45 @@ SYM_FUNC_START(entry_untrain_ret)
|
||||
SYM_FUNC_END(entry_untrain_ret)
|
||||
__EXPORT_THUNK(entry_untrain_ret)
|
||||
|
||||
#ifdef CONFIG_MITIGATION_ITS
|
||||
|
||||
.macro ITS_THUNK reg
|
||||
|
||||
SYM_INNER_LABEL(__x86_indirect_its_thunk_\reg, SYM_L_GLOBAL)
|
||||
UNWIND_HINT_EMPTY
|
||||
ANNOTATE_NOENDBR
|
||||
ANNOTATE_RETPOLINE_SAFE
|
||||
jmp *%\reg
|
||||
int3
|
||||
.align 32, 0xcc /* fill to the end of the line */
|
||||
.skip 32, 0xcc /* skip to the next upper half */
|
||||
.endm
|
||||
|
||||
/* ITS mitigation requires thunks be aligned to upper half of cacheline */
|
||||
.align 64, 0xcc
|
||||
.skip 32, 0xcc
|
||||
SYM_CODE_START(__x86_indirect_its_thunk_array)
|
||||
|
||||
#define GEN(reg) ITS_THUNK reg
|
||||
#include <asm/GEN-for-each-reg.h>
|
||||
#undef GEN
|
||||
|
||||
.align 64, 0xcc
|
||||
SYM_CODE_END(__x86_indirect_its_thunk_array)
|
||||
|
||||
.align 64, 0xcc
|
||||
.skip 32, 0xcc
|
||||
SYM_CODE_START(its_return_thunk)
|
||||
UNWIND_HINT_FUNC
|
||||
ANNOTATE_NOENDBR
|
||||
ANNOTATE_UNRET_SAFE
|
||||
ret
|
||||
int3
|
||||
SYM_CODE_END(its_return_thunk)
|
||||
EXPORT_SYMBOL(its_return_thunk)
|
||||
|
||||
#endif /* CONFIG_MITIGATION_ITS */
|
||||
|
||||
SYM_CODE_START(__x86_return_thunk)
|
||||
UNWIND_HINT_FUNC
|
||||
ANNOTATE_NOENDBR
|
||||
|
||||
@@ -660,8 +660,13 @@ static void __init memory_map_top_down(unsigned long map_start,
|
||||
*/
|
||||
addr = memblock_phys_alloc_range(PMD_SIZE, PMD_SIZE, map_start,
|
||||
map_end);
|
||||
memblock_phys_free(addr, PMD_SIZE);
|
||||
real_end = addr + PMD_SIZE;
|
||||
if (!addr) {
|
||||
pr_warn("Failed to release memory for alloc_low_pages()");
|
||||
real_end = max(map_start, ALIGN_DOWN(map_end, PMD_SIZE));
|
||||
} else {
|
||||
memblock_phys_free(addr, PMD_SIZE);
|
||||
real_end = addr + PMD_SIZE;
|
||||
}
|
||||
|
||||
/* step_size need to be small so pgt_buf from BRK could cover it */
|
||||
step_size = PMD_SIZE;
|
||||
|
||||
@@ -959,9 +959,18 @@ int add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages,
|
||||
ret = __add_pages(nid, start_pfn, nr_pages, params);
|
||||
WARN_ON_ONCE(ret);
|
||||
|
||||
/* update max_pfn, max_low_pfn and high_memory */
|
||||
update_end_of_memory_vars(start_pfn << PAGE_SHIFT,
|
||||
nr_pages << PAGE_SHIFT);
|
||||
/*
|
||||
* Special case: add_pages() is called by memremap_pages() for adding device
|
||||
* private pages. Do not bump up max_pfn in the device private path,
|
||||
* because max_pfn changes affect dma_addressing_limited().
|
||||
*
|
||||
* dma_addressing_limited() returning true when max_pfn is the device's
|
||||
* addressable memory can force device drivers to use bounce buffers
|
||||
* and impact their performance negatively:
|
||||
*/
|
||||
if (!params->pgmap)
|
||||
/* update max_pfn, max_low_pfn and high_memory */
|
||||
update_end_of_memory_vars(start_pfn << PAGE_SHIFT, nr_pages << PAGE_SHIFT);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -109,8 +109,14 @@ void __init kernel_randomize_memory(void)
|
||||
memory_tb = DIV_ROUND_UP(max_pfn << PAGE_SHIFT, 1UL << TB_SHIFT) +
|
||||
CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING;
|
||||
|
||||
/* Adapt physical memory region size based on available memory */
|
||||
if (memory_tb < kaslr_regions[0].size_tb)
|
||||
/*
|
||||
* Adapt physical memory region size based on available memory,
|
||||
* except when CONFIG_PCI_P2PDMA is enabled. P2PDMA exposes the
|
||||
* device BAR space assuming the direct map space is large enough
|
||||
* for creating a ZONE_DEVICE mapping in the direct map corresponding
|
||||
* to the physical BAR address.
|
||||
*/
|
||||
if (!IS_ENABLED(CONFIG_PCI_P2PDMA) && (memory_tb < kaslr_regions[0].size_tb))
|
||||
kaslr_regions[0].size_tb = memory_tb;
|
||||
|
||||
/*
|
||||
|
||||
@@ -617,7 +617,11 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
|
||||
|
||||
choose_new_asid(next, next_tlb_gen, &new_asid, &need_flush);
|
||||
|
||||
/* Let nmi_uaccess_okay() know that we're changing CR3. */
|
||||
/*
|
||||
* Indicate that CR3 is about to change. nmi_uaccess_okay()
|
||||
* and others are sensitive to the window where mm_cpumask(),
|
||||
* CR3 and cpu_tlbstate.loaded_mm are not all in sync.
|
||||
*/
|
||||
this_cpu_write(cpu_tlbstate.loaded_mm, LOADED_MM_SWITCHING);
|
||||
barrier();
|
||||
}
|
||||
@@ -880,8 +884,16 @@ done:
|
||||
|
||||
static bool should_flush_tlb(int cpu, void *data)
|
||||
{
|
||||
struct mm_struct *loaded_mm = per_cpu(cpu_tlbstate.loaded_mm, cpu);
|
||||
struct flush_tlb_info *info = data;
|
||||
|
||||
/*
|
||||
* Order the 'loaded_mm' and 'is_lazy' against their
|
||||
* write ordering in switch_mm_irqs_off(). Ensure
|
||||
* 'is_lazy' is at least as new as 'loaded_mm'.
|
||||
*/
|
||||
smp_rmb();
|
||||
|
||||
/* Lazy TLB will get flushed at the next context switch. */
|
||||
if (per_cpu(cpu_tlbstate_shared.is_lazy, cpu))
|
||||
return false;
|
||||
@@ -890,8 +902,15 @@ static bool should_flush_tlb(int cpu, void *data)
|
||||
if (!info->mm)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* While switching, the remote CPU could have state from
|
||||
* either the prev or next mm. Assume the worst and flush.
|
||||
*/
|
||||
if (loaded_mm == LOADED_MM_SWITCHING)
|
||||
return true;
|
||||
|
||||
/* The target mm is loaded, and the CPU is not lazy. */
|
||||
if (per_cpu(cpu_tlbstate.loaded_mm, cpu) == info->mm)
|
||||
if (loaded_mm == info->mm)
|
||||
return true;
|
||||
|
||||
/* In cpumask, but not the loaded mm? Periodically remove by flushing. */
|
||||
|
||||
@@ -36,6 +36,8 @@ static u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len)
|
||||
#define EMIT2(b1, b2) EMIT((b1) + ((b2) << 8), 2)
|
||||
#define EMIT3(b1, b2, b3) EMIT((b1) + ((b2) << 8) + ((b3) << 16), 3)
|
||||
#define EMIT4(b1, b2, b3, b4) EMIT((b1) + ((b2) << 8) + ((b3) << 16) + ((b4) << 24), 4)
|
||||
#define EMIT5(b1, b2, b3, b4, b5) \
|
||||
do { EMIT1(b1); EMIT4(b2, b3, b4, b5); } while (0)
|
||||
|
||||
#define EMIT1_off32(b1, off) \
|
||||
do { EMIT1(b1); EMIT(off, 4); } while (0)
|
||||
@@ -462,7 +464,11 @@ static void emit_indirect_jump(u8 **pprog, int reg, u8 *ip)
|
||||
{
|
||||
u8 *prog = *pprog;
|
||||
|
||||
if (cpu_feature_enabled(X86_FEATURE_RETPOLINE_LFENCE)) {
|
||||
if (IS_ENABLED(CONFIG_MITIGATION_ITS) &&
|
||||
cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) {
|
||||
OPTIMIZER_HIDE_VAR(reg);
|
||||
emit_jump(&prog, its_static_thunk(reg), ip);
|
||||
} else if (cpu_feature_enabled(X86_FEATURE_RETPOLINE_LFENCE)) {
|
||||
EMIT_LFENCE();
|
||||
EMIT2(0xFF, 0xE0 + reg);
|
||||
} else if (cpu_feature_enabled(X86_FEATURE_RETPOLINE)) {
|
||||
@@ -481,7 +487,7 @@ static void emit_return(u8 **pprog, u8 *ip)
|
||||
{
|
||||
u8 *prog = *pprog;
|
||||
|
||||
if (cpu_feature_enabled(X86_FEATURE_RETHUNK)) {
|
||||
if (cpu_wants_rethunk()) {
|
||||
emit_jump(&prog, x86_return_thunk, ip);
|
||||
} else {
|
||||
EMIT1(0xC3); /* ret */
|
||||
@@ -947,6 +953,47 @@ static void emit_nops(u8 **pprog, int len)
|
||||
#define RESTORE_TAIL_CALL_CNT(stack) \
|
||||
EMIT3_off32(0x48, 0x8B, 0x85, -round_up(stack, 8) - 8)
|
||||
|
||||
static int emit_spectre_bhb_barrier(u8 **pprog, u8 *ip,
|
||||
struct bpf_prog *bpf_prog)
|
||||
{
|
||||
u8 *prog = *pprog;
|
||||
u8 *func;
|
||||
|
||||
if (cpu_feature_enabled(X86_FEATURE_CLEAR_BHB_LOOP)) {
|
||||
/* The clearing sequence clobbers eax and ecx. */
|
||||
EMIT1(0x50); /* push rax */
|
||||
EMIT1(0x51); /* push rcx */
|
||||
ip += 2;
|
||||
|
||||
func = (u8 *)clear_bhb_loop;
|
||||
|
||||
if (emit_call(&prog, func, ip))
|
||||
return -EINVAL;
|
||||
EMIT1(0x59); /* pop rcx */
|
||||
EMIT1(0x58); /* pop rax */
|
||||
}
|
||||
/* Insert IBHF instruction */
|
||||
if ((cpu_feature_enabled(X86_FEATURE_CLEAR_BHB_LOOP) &&
|
||||
cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) ||
|
||||
cpu_feature_enabled(X86_FEATURE_CLEAR_BHB_HW)) {
|
||||
/*
|
||||
* Add an Indirect Branch History Fence (IBHF). IBHF acts as a
|
||||
* fence preventing branch history from before the fence from
|
||||
* affecting indirect branches after the fence. This is
|
||||
* specifically used in cBPF jitted code to prevent Intra-mode
|
||||
* BHI attacks. The IBHF instruction is designed to be a NOP on
|
||||
* hardware that doesn't need or support it. The REP and REX.W
|
||||
* prefixes are required by the microcode, and they also ensure
|
||||
* that the NOP is unlikely to be used in existing code.
|
||||
*
|
||||
* IBHF is not a valid instruction in 32-bit mode.
|
||||
*/
|
||||
EMIT5(0xF3, 0x48, 0x0F, 0x1E, 0xF8); /* ibhf */
|
||||
}
|
||||
*pprog = prog;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image,
|
||||
int oldproglen, struct jit_context *ctx, bool jmp_padding)
|
||||
{
|
||||
@@ -1752,6 +1799,15 @@ emit_jmp:
|
||||
seen_exit = true;
|
||||
/* Update cleanup_addr */
|
||||
ctx->cleanup_addr = proglen;
|
||||
|
||||
if (bpf_prog_was_classic(bpf_prog) &&
|
||||
!capable(CAP_SYS_ADMIN)) {
|
||||
u8 *ip = image + addrs[i - 1];
|
||||
|
||||
if (emit_spectre_bhb_barrier(&prog, ip, bpf_prog))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pop_callee_regs(&prog, callee_regs_used);
|
||||
EMIT1(0xC9); /* leave */
|
||||
emit_return(&prog, image + addrs[i - 1] + (prog - temp));
|
||||
|
||||
@@ -26,7 +26,6 @@ void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc)
|
||||
COPY(RIP);
|
||||
COPY2(EFLAGS, EFL);
|
||||
COPY2(CS, CSGSFS);
|
||||
regs->gp[CS / sizeof(unsigned long)] &= 0xffff;
|
||||
regs->gp[CS / sizeof(unsigned long)] |= 3;
|
||||
regs->gp[SS / sizeof(unsigned long)] = mc->gregs[REG_CSGSFS] >> 48;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -579,7 +579,7 @@ struct bio *bio_kmalloc(unsigned short nr_vecs, gfp_t gfp_mask)
|
||||
{
|
||||
struct bio *bio;
|
||||
|
||||
if (nr_vecs > UIO_MAXIOV)
|
||||
if (nr_vecs > BIO_MAX_INLINE_VECS)
|
||||
return NULL;
|
||||
return kmalloc(struct_size(bio, bi_inline_vecs, nr_vecs), gfp_mask);
|
||||
}
|
||||
|
||||
@@ -263,10 +263,6 @@ static int hash_accept(struct socket *sock, struct socket *newsock, int flags,
|
||||
return err;
|
||||
|
||||
err = crypto_ahash_import(&ctx2->req, state);
|
||||
if (err) {
|
||||
sock_orphan(sk2);
|
||||
sock_put(sk2);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ static int __lzorle_compress(const u8 *src, unsigned int slen,
|
||||
size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
|
||||
int err;
|
||||
|
||||
err = lzorle1x_1_compress(src, slen, dst, &tmp_len, ctx);
|
||||
err = lzorle1x_1_compress_safe(src, slen, dst, &tmp_len, ctx);
|
||||
|
||||
if (err != LZO_E_OK)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -55,7 +55,7 @@ static int __lzo_compress(const u8 *src, unsigned int slen,
|
||||
size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
|
||||
int err;
|
||||
|
||||
err = lzo1x_1_compress(src, slen, dst, &tmp_len, ctx);
|
||||
err = lzo1x_1_compress_safe(src, slen, dst, &tmp_len, ctx);
|
||||
|
||||
if (err != LZO_E_OK)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -438,7 +438,7 @@ config ACPI_SBS
|
||||
the modules will be called sbs and sbshc.
|
||||
|
||||
config ACPI_HED
|
||||
tristate "Hardware Error Device"
|
||||
bool "Hardware Error Device"
|
||||
help
|
||||
This driver supports the Hardware Error Device (PNP0C33),
|
||||
which is used to report some hardware errors notified via
|
||||
|
||||
@@ -72,7 +72,12 @@ static struct acpi_driver acpi_hed_driver = {
|
||||
.notify = acpi_hed_notify,
|
||||
},
|
||||
};
|
||||
module_acpi_driver(acpi_hed_driver);
|
||||
|
||||
static int __init acpi_hed_driver_init(void)
|
||||
{
|
||||
return acpi_bus_register_driver(&acpi_hed_driver);
|
||||
}
|
||||
subsys_initcall(acpi_hed_driver_init);
|
||||
|
||||
MODULE_AUTHOR("Huang Ying");
|
||||
MODULE_DESCRIPTION("ACPI Hardware Error Device Driver");
|
||||
|
||||
@@ -219,16 +219,18 @@ static int acpi_pptt_leaf_node(struct acpi_table_header *table_hdr,
|
||||
sizeof(struct acpi_table_pptt));
|
||||
proc_sz = sizeof(struct acpi_pptt_processor);
|
||||
|
||||
while ((unsigned long)entry + proc_sz < table_end) {
|
||||
/* ignore subtable types that are smaller than a processor node */
|
||||
while ((unsigned long)entry + proc_sz <= table_end) {
|
||||
cpu_node = (struct acpi_pptt_processor *)entry;
|
||||
|
||||
if (entry->type == ACPI_PPTT_TYPE_PROCESSOR &&
|
||||
cpu_node->parent == node_entry)
|
||||
return 0;
|
||||
if (entry->length == 0)
|
||||
return 0;
|
||||
|
||||
entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry,
|
||||
entry->length);
|
||||
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -261,15 +263,18 @@ static struct acpi_pptt_processor *acpi_find_processor_node(struct acpi_table_he
|
||||
proc_sz = sizeof(struct acpi_pptt_processor);
|
||||
|
||||
/* find the processor structure associated with this cpuid */
|
||||
while ((unsigned long)entry + proc_sz < table_end) {
|
||||
while ((unsigned long)entry + proc_sz <= table_end) {
|
||||
cpu_node = (struct acpi_pptt_processor *)entry;
|
||||
|
||||
if (entry->length == 0) {
|
||||
pr_warn("Invalid zero length subtable\n");
|
||||
break;
|
||||
}
|
||||
/* entry->length may not equal proc_sz, revalidate the processor structure length */
|
||||
if (entry->type == ACPI_PPTT_TYPE_PROCESSOR &&
|
||||
acpi_cpu_id == cpu_node->acpi_processor_id &&
|
||||
(unsigned long)entry + entry->length <= table_end &&
|
||||
entry->length == proc_sz + cpu_node->number_of_priv_resources * sizeof(u32) &&
|
||||
acpi_pptt_leaf_node(table_hdr, cpu_node)) {
|
||||
return (struct acpi_pptt_processor *)entry;
|
||||
}
|
||||
|
||||
@@ -594,18 +594,19 @@ static int charlcd_init(struct charlcd *lcd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct charlcd *charlcd_alloc(void)
|
||||
struct charlcd *charlcd_alloc(unsigned int drvdata_size)
|
||||
{
|
||||
struct charlcd_priv *priv;
|
||||
struct charlcd *lcd;
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
priv = kzalloc(sizeof(*priv) + drvdata_size, GFP_KERNEL);
|
||||
if (!priv)
|
||||
return NULL;
|
||||
|
||||
priv->esc_seq.len = -1;
|
||||
|
||||
lcd = &priv->lcd;
|
||||
lcd->drvdata = priv->drvdata;
|
||||
|
||||
return lcd;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ struct charlcd {
|
||||
unsigned long y;
|
||||
} addr;
|
||||
|
||||
void *drvdata;
|
||||
void *drvdata; /* Set by charlcd_alloc() */
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -93,7 +93,8 @@ struct charlcd_ops {
|
||||
};
|
||||
|
||||
void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on);
|
||||
struct charlcd *charlcd_alloc(void);
|
||||
|
||||
struct charlcd *charlcd_alloc(unsigned int drvdata_size);
|
||||
void charlcd_free(struct charlcd *lcd);
|
||||
|
||||
int charlcd_register(struct charlcd *lcd);
|
||||
|
||||
@@ -226,7 +226,7 @@ static int hd44780_probe(struct platform_device *pdev)
|
||||
if (!hdc)
|
||||
return -ENOMEM;
|
||||
|
||||
lcd = charlcd_alloc();
|
||||
lcd = charlcd_alloc(0);
|
||||
if (!lcd)
|
||||
goto fail1;
|
||||
|
||||
|
||||
@@ -307,7 +307,7 @@ static int lcd2s_i2c_probe(struct i2c_client *i2c)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
lcd = charlcd_alloc();
|
||||
lcd = charlcd_alloc(0);
|
||||
if (!lcd)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@@ -835,7 +835,7 @@ static void lcd_init(void)
|
||||
if (!hdc)
|
||||
return;
|
||||
|
||||
charlcd = charlcd_alloc();
|
||||
charlcd = charlcd_alloc(0);
|
||||
if (!charlcd) {
|
||||
kfree(hdc);
|
||||
return;
|
||||
|
||||
@@ -595,6 +595,12 @@ ssize_t __weak cpu_show_reg_file_data_sampling(struct device *dev,
|
||||
return sysfs_emit(buf, "Not affected\n");
|
||||
}
|
||||
|
||||
ssize_t __weak cpu_show_indirect_target_selection(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "Not affected\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
|
||||
static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
|
||||
static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL);
|
||||
@@ -609,6 +615,7 @@ static DEVICE_ATTR(retbleed, 0444, cpu_show_retbleed, NULL);
|
||||
static DEVICE_ATTR(gather_data_sampling, 0444, cpu_show_gds, NULL);
|
||||
static DEVICE_ATTR(spec_rstack_overflow, 0444, cpu_show_spec_rstack_overflow, NULL);
|
||||
static DEVICE_ATTR(reg_file_data_sampling, 0444, cpu_show_reg_file_data_sampling, NULL);
|
||||
static DEVICE_ATTR(indirect_target_selection, 0444, cpu_show_indirect_target_selection, NULL);
|
||||
|
||||
static struct attribute *cpu_root_vulnerabilities_attrs[] = {
|
||||
&dev_attr_meltdown.attr,
|
||||
@@ -625,6 +632,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
|
||||
&dev_attr_gather_data_sampling.attr,
|
||||
&dev_attr_spec_rstack_overflow.attr,
|
||||
&dev_attr_reg_file_data_sampling.attr,
|
||||
&dev_attr_indirect_target_selection.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ enum tis_int_flags {
|
||||
enum tis_defaults {
|
||||
TIS_MEM_LEN = 0x5000,
|
||||
TIS_SHORT_TIMEOUT = 750, /* ms */
|
||||
TIS_LONG_TIMEOUT = 2000, /* 2 sec */
|
||||
TIS_LONG_TIMEOUT = 4000, /* 4 secs */
|
||||
TIS_TIMEOUT_MIN_ATML = 14700, /* usecs */
|
||||
TIS_TIMEOUT_MAX_ATML = 15000, /* usecs */
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/units.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -405,11 +406,151 @@ static const char * const imx8mp_clkout_sels[] = {"audio_pll1_out", "audio_pll2_
|
||||
static struct clk_hw **hws;
|
||||
static struct clk_hw_onecell_data *clk_hw_data;
|
||||
|
||||
struct imx8mp_clock_constraints {
|
||||
unsigned int clkid;
|
||||
u32 maxrate;
|
||||
};
|
||||
|
||||
/*
|
||||
* Below tables are taken from IMX8MPCEC Rev. 2.1, 07/2023
|
||||
* Table 13. Maximum frequency of modules.
|
||||
* Probable typos fixed are marked with a comment.
|
||||
*/
|
||||
static const struct imx8mp_clock_constraints imx8mp_clock_common_constraints[] = {
|
||||
{ IMX8MP_CLK_A53_DIV, 1000 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_ENET_AXI, 266666667 }, /* Datasheet claims 266MHz */
|
||||
{ IMX8MP_CLK_NAND_USDHC_BUS, 266666667 }, /* Datasheet claims 266MHz */
|
||||
{ IMX8MP_CLK_MEDIA_APB, 200 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_HDMI_APB, 133333333 }, /* Datasheet claims 133MHz */
|
||||
{ IMX8MP_CLK_ML_AXI, 800 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_AHB, 133333333 },
|
||||
{ IMX8MP_CLK_IPG_ROOT, 66666667 },
|
||||
{ IMX8MP_CLK_AUDIO_AHB, 400 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_MEDIA_DISP2_PIX, 170 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_DRAM_ALT, 666666667 },
|
||||
{ IMX8MP_CLK_DRAM_APB, 200 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_CAN1, 80 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_CAN2, 80 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_PCIE_AUX, 10 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_I2C5, 66666667 }, /* Datasheet claims 66MHz */
|
||||
{ IMX8MP_CLK_I2C6, 66666667 }, /* Datasheet claims 66MHz */
|
||||
{ IMX8MP_CLK_SAI1, 66666667 }, /* Datasheet claims 66MHz */
|
||||
{ IMX8MP_CLK_SAI2, 66666667 }, /* Datasheet claims 66MHz */
|
||||
{ IMX8MP_CLK_SAI3, 66666667 }, /* Datasheet claims 66MHz */
|
||||
{ IMX8MP_CLK_SAI5, 66666667 }, /* Datasheet claims 66MHz */
|
||||
{ IMX8MP_CLK_SAI6, 66666667 }, /* Datasheet claims 66MHz */
|
||||
{ IMX8MP_CLK_ENET_QOS, 125 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_ENET_QOS_TIMER, 200 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_ENET_REF, 125 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_ENET_TIMER, 125 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_ENET_PHY_REF, 125 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_NAND, 500 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_QSPI, 400 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_USDHC1, 400 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_USDHC2, 400 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_I2C1, 66666667 }, /* Datasheet claims 66MHz */
|
||||
{ IMX8MP_CLK_I2C2, 66666667 }, /* Datasheet claims 66MHz */
|
||||
{ IMX8MP_CLK_I2C3, 66666667 }, /* Datasheet claims 66MHz */
|
||||
{ IMX8MP_CLK_I2C4, 66666667 }, /* Datasheet claims 66MHz */
|
||||
{ IMX8MP_CLK_UART1, 80 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_UART2, 80 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_UART3, 80 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_UART4, 80 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_ECSPI1, 80 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_ECSPI2, 80 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_PWM1, 66666667 }, /* Datasheet claims 66MHz */
|
||||
{ IMX8MP_CLK_PWM2, 66666667 }, /* Datasheet claims 66MHz */
|
||||
{ IMX8MP_CLK_PWM3, 66666667 }, /* Datasheet claims 66MHz */
|
||||
{ IMX8MP_CLK_PWM4, 66666667 }, /* Datasheet claims 66MHz */
|
||||
{ IMX8MP_CLK_GPT1, 100 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_GPT2, 100 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_GPT3, 100 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_GPT4, 100 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_GPT5, 100 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_GPT6, 100 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_WDOG, 66666667 }, /* Datasheet claims 66MHz */
|
||||
{ IMX8MP_CLK_IPP_DO_CLKO1, 200 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_IPP_DO_CLKO2, 200 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_HDMI_REF_266M, 266 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_USDHC3, 400 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_MEDIA_MIPI_PHY1_REF, 300 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_MEDIA_DISP1_PIX, 250 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_MEDIA_CAM2_PIX, 277 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_MEDIA_LDB, 595 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_MEDIA_MIPI_TEST_BYTE, 200 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_ECSPI3, 80 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_PDM, 200 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_SAI7, 66666667 }, /* Datasheet claims 66MHz */
|
||||
{ IMX8MP_CLK_MAIN_AXI, 400 * HZ_PER_MHZ },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
|
||||
static const struct imx8mp_clock_constraints imx8mp_clock_nominal_constraints[] = {
|
||||
{ IMX8MP_CLK_M7_CORE, 600 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_ML_CORE, 800 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_GPU3D_CORE, 800 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_GPU3D_SHADER_CORE, 800 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_GPU2D_CORE, 800 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_AUDIO_AXI_SRC, 600 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_HSIO_AXI, 400 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_MEDIA_ISP, 400 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_VPU_BUS, 600 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_MEDIA_AXI, 400 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_HDMI_AXI, 400 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_GPU_AXI, 600 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_GPU_AHB, 300 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_NOC, 800 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_NOC_IO, 600 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_ML_AHB, 300 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_VPU_G1, 600 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_VPU_G2, 500 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_MEDIA_CAM1_PIX, 400 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_VPU_VC8000E, 400 * HZ_PER_MHZ }, /* Datasheet claims 500MHz */
|
||||
{ IMX8MP_CLK_DRAM_CORE, 800 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_GIC, 400 * HZ_PER_MHZ },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
|
||||
static const struct imx8mp_clock_constraints imx8mp_clock_overdrive_constraints[] = {
|
||||
{ IMX8MP_CLK_M7_CORE, 800 * HZ_PER_MHZ},
|
||||
{ IMX8MP_CLK_ML_CORE, 1000 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_GPU3D_CORE, 1000 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_GPU3D_SHADER_CORE, 1000 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_GPU2D_CORE, 1000 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_AUDIO_AXI_SRC, 800 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_HSIO_AXI, 500 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_MEDIA_ISP, 500 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_VPU_BUS, 800 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_MEDIA_AXI, 500 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_HDMI_AXI, 500 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_GPU_AXI, 800 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_GPU_AHB, 400 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_NOC, 1000 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_NOC_IO, 800 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_ML_AHB, 400 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_VPU_G1, 800 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_VPU_G2, 700 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_MEDIA_CAM1_PIX, 500 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_VPU_VC8000E, 500 * HZ_PER_MHZ }, /* Datasheet claims 400MHz */
|
||||
{ IMX8MP_CLK_DRAM_CORE, 1000 * HZ_PER_MHZ },
|
||||
{ IMX8MP_CLK_GIC, 500 * HZ_PER_MHZ },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
|
||||
static void imx8mp_clocks_apply_constraints(const struct imx8mp_clock_constraints constraints[])
|
||||
{
|
||||
const struct imx8mp_clock_constraints *constr;
|
||||
|
||||
for (constr = constraints; constr->clkid; constr++)
|
||||
clk_hw_set_rate_range(hws[constr->clkid], 0, constr->maxrate);
|
||||
}
|
||||
|
||||
static int imx8mp_clocks_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np;
|
||||
void __iomem *anatop_base, *ccm_base;
|
||||
const char *opmode;
|
||||
int err;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mp-anatop");
|
||||
@@ -704,6 +845,16 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
|
||||
|
||||
imx_check_clk_hws(hws, IMX8MP_CLK_END);
|
||||
|
||||
imx8mp_clocks_apply_constraints(imx8mp_clock_common_constraints);
|
||||
|
||||
err = of_property_read_string(np, "fsl,operating-mode", &opmode);
|
||||
if (!err) {
|
||||
if (!strcmp(opmode, "nominal"))
|
||||
imx8mp_clocks_apply_constraints(imx8mp_clock_nominal_constraints);
|
||||
else if (!strcmp(opmode, "overdrive"))
|
||||
imx8mp_clocks_apply_constraints(imx8mp_clock_overdrive_constraints);
|
||||
}
|
||||
|
||||
err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "failed to register hws for i.MX8MP\n");
|
||||
|
||||
@@ -411,7 +411,7 @@ static struct clk_rcg2 cam_cc_bps_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -433,7 +433,7 @@ static struct clk_rcg2 cam_cc_camnoc_axi_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -454,7 +454,7 @@ static struct clk_rcg2 cam_cc_cci_0_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -469,7 +469,7 @@ static struct clk_rcg2 cam_cc_cci_1_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -490,7 +490,7 @@ static struct clk_rcg2 cam_cc_cphy_rx_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -511,7 +511,7 @@ static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -526,7 +526,7 @@ static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -556,7 +556,7 @@ static struct clk_rcg2 cam_cc_csi3phytimer_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -571,7 +571,7 @@ static struct clk_rcg2 cam_cc_csi4phytimer_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -586,7 +586,7 @@ static struct clk_rcg2 cam_cc_csi5phytimer_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -611,7 +611,7 @@ static struct clk_rcg2 cam_cc_fast_ahb_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -634,7 +634,7 @@ static struct clk_rcg2 cam_cc_fd_core_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -649,7 +649,7 @@ static struct clk_rcg2 cam_cc_icp_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -673,7 +673,7 @@ static struct clk_rcg2 cam_cc_ife_0_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_2,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_2),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -710,7 +710,7 @@ static struct clk_rcg2 cam_cc_ife_0_csid_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -734,7 +734,7 @@ static struct clk_rcg2 cam_cc_ife_1_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_3,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_3),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -749,7 +749,7 @@ static struct clk_rcg2 cam_cc_ife_1_csid_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -771,7 +771,7 @@ static struct clk_rcg2 cam_cc_ife_lite_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -786,7 +786,7 @@ static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -810,7 +810,7 @@ static struct clk_rcg2 cam_cc_ipe_0_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_4,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_4),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -825,7 +825,7 @@ static struct clk_rcg2 cam_cc_jpeg_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -847,7 +847,7 @@ static struct clk_rcg2 cam_cc_mclk0_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_1,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -862,7 +862,7 @@ static struct clk_rcg2 cam_cc_mclk1_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_1,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -877,7 +877,7 @@ static struct clk_rcg2 cam_cc_mclk2_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_1,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -892,7 +892,7 @@ static struct clk_rcg2 cam_cc_mclk3_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_1,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -907,7 +907,7 @@ static struct clk_rcg2 cam_cc_mclk4_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_1,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -922,7 +922,7 @@ static struct clk_rcg2 cam_cc_mclk5_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_1,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -993,7 +993,7 @@ static struct clk_rcg2 cam_cc_slow_ahb_clk_src = {
|
||||
.parent_data = cam_cc_parent_data_0,
|
||||
.num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_ops,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -561,14 +561,19 @@ clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
u32 alpha_width = pll_alpha_width(pll);
|
||||
|
||||
regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);
|
||||
if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l))
|
||||
return 0;
|
||||
|
||||
if (regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl))
|
||||
return 0;
|
||||
|
||||
regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl);
|
||||
if (ctl & PLL_ALPHA_EN) {
|
||||
regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &low);
|
||||
if (regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &low))
|
||||
return 0;
|
||||
if (alpha_width > 32) {
|
||||
regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll),
|
||||
&high);
|
||||
if (regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll),
|
||||
&high))
|
||||
return 0;
|
||||
a = (u64)high << 32 | low;
|
||||
} else {
|
||||
a = low & GENMASK(alpha_width - 1, 0);
|
||||
@@ -760,8 +765,11 @@ alpha_pll_huayra_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
u32 l, alpha = 0, ctl, alpha_m, alpha_n;
|
||||
|
||||
regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);
|
||||
regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl);
|
||||
if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l))
|
||||
return 0;
|
||||
|
||||
if (regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl))
|
||||
return 0;
|
||||
|
||||
if (ctl & PLL_ALPHA_EN) {
|
||||
regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &alpha);
|
||||
@@ -955,8 +963,11 @@ clk_trion_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
u32 l, frac, alpha_width = pll_alpha_width(pll);
|
||||
|
||||
regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);
|
||||
regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &frac);
|
||||
if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l))
|
||||
return 0;
|
||||
|
||||
if (regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &frac))
|
||||
return 0;
|
||||
|
||||
return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width);
|
||||
}
|
||||
@@ -1014,7 +1025,8 @@ clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
||||
struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
|
||||
u32 ctl;
|
||||
|
||||
regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl);
|
||||
if (regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl))
|
||||
return 0;
|
||||
|
||||
ctl >>= PLL_POST_DIV_SHIFT;
|
||||
ctl &= PLL_POST_DIV_MASK(pll);
|
||||
@@ -1230,8 +1242,11 @@ static unsigned long alpha_pll_fabia_recalc_rate(struct clk_hw *hw,
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
u32 l, frac, alpha_width = pll_alpha_width(pll);
|
||||
|
||||
regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);
|
||||
regmap_read(pll->clkr.regmap, PLL_FRAC(pll), &frac);
|
||||
if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l))
|
||||
return 0;
|
||||
|
||||
if (regmap_read(pll->clkr.regmap, PLL_FRAC(pll), &frac))
|
||||
return 0;
|
||||
|
||||
return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width);
|
||||
}
|
||||
@@ -1381,7 +1396,8 @@ clk_trion_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
||||
struct regmap *regmap = pll->clkr.regmap;
|
||||
u32 i, div = 1, val;
|
||||
|
||||
regmap_read(regmap, PLL_USER_CTL(pll), &val);
|
||||
if (regmap_read(regmap, PLL_USER_CTL(pll), &val))
|
||||
return 0;
|
||||
|
||||
val >>= pll->post_div_shift;
|
||||
val &= PLL_POST_DIV_MASK(pll);
|
||||
@@ -2254,9 +2270,12 @@ static unsigned long alpha_pll_lucid_evo_recalc_rate(struct clk_hw *hw,
|
||||
struct regmap *regmap = pll->clkr.regmap;
|
||||
u32 l, frac;
|
||||
|
||||
regmap_read(regmap, PLL_L_VAL(pll), &l);
|
||||
if (regmap_read(regmap, PLL_L_VAL(pll), &l))
|
||||
return 0;
|
||||
l &= LUCID_EVO_PLL_L_VAL_MASK;
|
||||
regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac);
|
||||
|
||||
if (regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac))
|
||||
return 0;
|
||||
|
||||
return alpha_pll_calc_rate(parent_rate, l, frac, pll_alpha_width(pll));
|
||||
}
|
||||
@@ -2331,7 +2350,8 @@ static unsigned long clk_rivian_evo_pll_recalc_rate(struct clk_hw *hw,
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
u32 l;
|
||||
|
||||
regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);
|
||||
if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l))
|
||||
return 0;
|
||||
|
||||
return parent_rate * l;
|
||||
}
|
||||
|
||||
@@ -412,19 +412,23 @@ static const struct clk_parent_data mmc0_mmc1_parents[] = {
|
||||
{ .hw = &pll_periph0_2x_clk.common.hw },
|
||||
{ .hw = &pll_audio1_div2_clk.common.hw },
|
||||
};
|
||||
static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc0_mmc1_parents, 0x830,
|
||||
0, 4, /* M */
|
||||
8, 2, /* P */
|
||||
24, 3, /* mux */
|
||||
BIT(31), /* gate */
|
||||
0);
|
||||
static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0",
|
||||
mmc0_mmc1_parents, 0x830,
|
||||
0, 4, /* M */
|
||||
8, 2, /* P */
|
||||
24, 3, /* mux */
|
||||
BIT(31), /* gate */
|
||||
2, /* post-div */
|
||||
0);
|
||||
|
||||
static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc0_mmc1_parents, 0x834,
|
||||
0, 4, /* M */
|
||||
8, 2, /* P */
|
||||
24, 3, /* mux */
|
||||
BIT(31), /* gate */
|
||||
0);
|
||||
static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1",
|
||||
mmc0_mmc1_parents, 0x834,
|
||||
0, 4, /* M */
|
||||
8, 2, /* P */
|
||||
24, 3, /* mux */
|
||||
BIT(31), /* gate */
|
||||
2, /* post-div */
|
||||
0);
|
||||
|
||||
static const struct clk_parent_data mmc2_parents[] = {
|
||||
{ .fw_name = "hosc" },
|
||||
@@ -433,12 +437,14 @@ static const struct clk_parent_data mmc2_parents[] = {
|
||||
{ .hw = &pll_periph0_800M_clk.common.hw },
|
||||
{ .hw = &pll_audio1_div2_clk.common.hw },
|
||||
};
|
||||
static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc2_parents, 0x838,
|
||||
0, 4, /* M */
|
||||
8, 2, /* P */
|
||||
24, 3, /* mux */
|
||||
BIT(31), /* gate */
|
||||
0);
|
||||
static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_POSTDIV(mmc2_clk, "mmc2", mmc2_parents,
|
||||
0x838,
|
||||
0, 4, /* M */
|
||||
8, 2, /* P */
|
||||
24, 3, /* mux */
|
||||
BIT(31), /* gate */
|
||||
2, /* post-div */
|
||||
0);
|
||||
|
||||
static SUNXI_CCU_GATE_HWS(bus_mmc0_clk, "bus-mmc0", psi_ahb_hws,
|
||||
0x84c, BIT(0), 0);
|
||||
|
||||
@@ -52,6 +52,28 @@ struct ccu_mp {
|
||||
} \
|
||||
}
|
||||
|
||||
#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE_POSTDIV(_struct, _name, _parents, \
|
||||
_reg, \
|
||||
_mshift, _mwidth, \
|
||||
_pshift, _pwidth, \
|
||||
_muxshift, _muxwidth, \
|
||||
_gate, _postdiv, _flags)\
|
||||
struct ccu_mp _struct = { \
|
||||
.enable = _gate, \
|
||||
.m = _SUNXI_CCU_DIV(_mshift, _mwidth), \
|
||||
.p = _SUNXI_CCU_DIV(_pshift, _pwidth), \
|
||||
.mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
|
||||
.fixed_post_div = _postdiv, \
|
||||
.common = { \
|
||||
.reg = _reg, \
|
||||
.features = CCU_FEATURE_FIXED_POSTDIV, \
|
||||
.hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \
|
||||
_parents, \
|
||||
&ccu_mp_ops, \
|
||||
_flags), \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
|
||||
_mshift, _mwidth, \
|
||||
_pshift, _pwidth, \
|
||||
|
||||
@@ -103,7 +103,7 @@ int __init clocksource_i8253_init(void)
|
||||
#ifdef CONFIG_CLKEVT_I8253
|
||||
void clockevent_i8253_disable(void)
|
||||
{
|
||||
raw_spin_lock(&i8253_lock);
|
||||
guard(raw_spinlock_irqsave)(&i8253_lock);
|
||||
|
||||
/*
|
||||
* Writing the MODE register should stop the counter, according to
|
||||
@@ -132,8 +132,6 @@ void clockevent_i8253_disable(void)
|
||||
outb_p(0, PIT_CH0);
|
||||
|
||||
outb_p(0x30, PIT_MODE);
|
||||
|
||||
raw_spin_unlock(&i8253_lock);
|
||||
}
|
||||
|
||||
static int pit_shutdown(struct clock_event_device *evt)
|
||||
|
||||
@@ -114,6 +114,9 @@ static void gic_update_frequency(void *data)
|
||||
|
||||
static int gic_starting_cpu(unsigned int cpu)
|
||||
{
|
||||
/* Ensure the GIC counter is running */
|
||||
clear_gic_config(GIC_CONFIG_COUNTSTOP);
|
||||
|
||||
gic_clockevent_cpu_init(cpu, this_cpu_ptr(&gic_clockevent_device));
|
||||
return 0;
|
||||
}
|
||||
@@ -248,9 +251,6 @@ static int __init gic_clocksource_of_init(struct device_node *node)
|
||||
pr_warn("Unable to register clock notifier\n");
|
||||
}
|
||||
|
||||
/* And finally start the counter */
|
||||
clear_gic_config(GIC_CONFIG_COUNTSTOP);
|
||||
|
||||
/*
|
||||
* It's safe to use the MIPS GIC timer as a sched clock source only if
|
||||
* its ticks are stable, which is true on either the platforms with
|
||||
|
||||
@@ -73,11 +73,18 @@ static int tegra186_cpufreq_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct tegra186_cpufreq_data *data = cpufreq_get_driver_data();
|
||||
unsigned int cluster = data->cpus[policy->cpu].bpmp_cluster_id;
|
||||
u32 cpu;
|
||||
|
||||
policy->freq_table = data->clusters[cluster].table;
|
||||
policy->cpuinfo.transition_latency = 300 * 1000;
|
||||
policy->driver_data = NULL;
|
||||
|
||||
/* set same policy for all cpus in a cluster */
|
||||
for (cpu = 0; cpu < ARRAY_SIZE(tegra186_cpus); cpu++) {
|
||||
if (data->cpus[cpu].bpmp_cluster_id == cluster)
|
||||
cpumask_set_cpu(cpu, policy->cpus);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -249,8 +249,19 @@ again:
|
||||
* This can deal with workloads that have long pauses interspersed
|
||||
* with sporadic activity with a bunch of short pauses.
|
||||
*/
|
||||
if ((divisor * 4) <= INTERVALS * 3)
|
||||
if (divisor * 4 <= INTERVALS * 3) {
|
||||
/*
|
||||
* If there are sufficiently many data points still under
|
||||
* consideration after the outliers have been eliminated,
|
||||
* returning without a prediction would be a mistake because it
|
||||
* is likely that the next interval will not exceed the current
|
||||
* maximum, so return the latter in that case.
|
||||
*/
|
||||
if (divisor >= INTERVALS / 2)
|
||||
return max;
|
||||
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
thresh = max - 1;
|
||||
goto again;
|
||||
|
||||
@@ -410,9 +410,10 @@ static int cpt_process_ccode(struct otx2_cptlfs_info *lfs,
|
||||
break;
|
||||
}
|
||||
|
||||
dev_err(&pdev->dev,
|
||||
"Request failed with software error code 0x%x\n",
|
||||
cpt_status->s.uc_compcode);
|
||||
pr_debug("Request failed with software error code 0x%x: algo = %s driver = %s\n",
|
||||
cpt_status->s.uc_compcode,
|
||||
info->req->areq->tfm->__crt_alg->cra_name,
|
||||
info->req->areq->tfm->__crt_alg->cra_driver_name);
|
||||
otx2_cpt_dump_sg_list(pdev, info->req);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -308,8 +308,9 @@ void dma_resv_add_fence(struct dma_resv *obj, struct dma_fence *fence,
|
||||
count++;
|
||||
|
||||
dma_resv_list_set(fobj, i, fence, usage);
|
||||
/* pointer update must be visible before we extend the num_fences */
|
||||
smp_store_mb(fobj->num_fences, count);
|
||||
/* fence update must be visible before we extend the num_fences */
|
||||
smp_wmb();
|
||||
fobj->num_fences = count;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_resv_add_fence);
|
||||
|
||||
|
||||
@@ -827,9 +827,9 @@ static int dmatest_func(void *data)
|
||||
} else {
|
||||
dma_async_issue_pending(chan);
|
||||
|
||||
wait_event_timeout(thread->done_wait,
|
||||
done->done,
|
||||
msecs_to_jiffies(params->timeout));
|
||||
wait_event_freezable_timeout(thread->done_wait,
|
||||
done->done,
|
||||
msecs_to_jiffies(params->timeout));
|
||||
|
||||
status = dma_async_is_tx_complete(chan, cookie, NULL,
|
||||
NULL);
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <uapi/linux/idxd.h>
|
||||
#include <linux/xarray.h>
|
||||
#include "registers.h"
|
||||
#include "idxd.h"
|
||||
|
||||
@@ -34,6 +36,7 @@ struct idxd_user_context {
|
||||
struct idxd_wq *wq;
|
||||
struct task_struct *task;
|
||||
unsigned int pasid;
|
||||
struct mm_struct *mm;
|
||||
unsigned int flags;
|
||||
struct iommu_sva *sva;
|
||||
};
|
||||
@@ -68,6 +71,19 @@ static inline struct idxd_wq *inode_wq(struct inode *inode)
|
||||
return idxd_cdev->wq;
|
||||
}
|
||||
|
||||
static void idxd_xa_pasid_remove(struct idxd_user_context *ctx)
|
||||
{
|
||||
struct idxd_wq *wq = ctx->wq;
|
||||
void *ptr;
|
||||
|
||||
mutex_lock(&wq->uc_lock);
|
||||
ptr = xa_cmpxchg(&wq->upasid_xa, ctx->pasid, ctx, NULL, GFP_KERNEL);
|
||||
if (ptr != (void *)ctx)
|
||||
dev_warn(&wq->idxd->pdev->dev, "xarray cmpxchg failed for pasid %u\n",
|
||||
ctx->pasid);
|
||||
mutex_unlock(&wq->uc_lock);
|
||||
}
|
||||
|
||||
static int idxd_cdev_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct idxd_user_context *ctx;
|
||||
@@ -108,20 +124,25 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
|
||||
|
||||
pasid = iommu_sva_get_pasid(sva);
|
||||
if (pasid == IOMMU_PASID_INVALID) {
|
||||
iommu_sva_unbind_device(sva);
|
||||
rc = -EINVAL;
|
||||
goto failed;
|
||||
goto failed_get_pasid;
|
||||
}
|
||||
|
||||
ctx->sva = sva;
|
||||
ctx->pasid = pasid;
|
||||
ctx->mm = current->mm;
|
||||
|
||||
mutex_lock(&wq->uc_lock);
|
||||
rc = xa_insert(&wq->upasid_xa, pasid, ctx, GFP_KERNEL);
|
||||
mutex_unlock(&wq->uc_lock);
|
||||
if (rc < 0)
|
||||
dev_warn(dev, "PASID entry already exist in xarray.\n");
|
||||
|
||||
if (wq_dedicated(wq)) {
|
||||
rc = idxd_wq_set_pasid(wq, pasid);
|
||||
if (rc < 0) {
|
||||
iommu_sva_unbind_device(sva);
|
||||
dev_err(dev, "wq set pasid failed: %d\n", rc);
|
||||
goto failed;
|
||||
goto failed_set_pasid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -130,7 +151,13 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
|
||||
mutex_unlock(&wq->wq_lock);
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
failed_set_pasid:
|
||||
if (device_user_pasid_enabled(idxd))
|
||||
idxd_xa_pasid_remove(ctx);
|
||||
failed_get_pasid:
|
||||
if (device_user_pasid_enabled(idxd))
|
||||
iommu_sva_unbind_device(sva);
|
||||
failed:
|
||||
mutex_unlock(&wq->wq_lock);
|
||||
kfree(ctx);
|
||||
return rc;
|
||||
@@ -161,8 +188,10 @@ static int idxd_cdev_release(struct inode *node, struct file *filep)
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->sva)
|
||||
if (ctx->sva) {
|
||||
iommu_sva_unbind_device(ctx->sva);
|
||||
idxd_xa_pasid_remove(ctx);
|
||||
}
|
||||
kfree(ctx);
|
||||
mutex_lock(&wq->wq_lock);
|
||||
idxd_wq_put(wq);
|
||||
@@ -209,6 +238,9 @@ static int idxd_cdev_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
if (!idxd->user_submission_safe && !capable(CAP_SYS_RAWIO))
|
||||
return -EPERM;
|
||||
|
||||
if (current->mm != ctx->mm)
|
||||
return -EPERM;
|
||||
|
||||
rc = check_vma(wq, vma, __func__);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
@@ -275,6 +307,9 @@ static ssize_t idxd_cdev_write(struct file *filp, const char __user *buf, size_t
|
||||
ssize_t written = 0;
|
||||
int i;
|
||||
|
||||
if (current->mm != ctx->mm)
|
||||
return -EPERM;
|
||||
|
||||
for (i = 0; i < len/sizeof(struct dsa_hw_desc); i++) {
|
||||
int rc = idxd_submit_user_descriptor(ctx, udesc + i);
|
||||
|
||||
@@ -295,6 +330,9 @@ static __poll_t idxd_cdev_poll(struct file *filp,
|
||||
struct idxd_device *idxd = wq->idxd;
|
||||
__poll_t out = 0;
|
||||
|
||||
if (current->mm != ctx->mm)
|
||||
return POLLNVAL;
|
||||
|
||||
poll_wait(filp, &wq->err_queue, wait);
|
||||
spin_lock(&idxd->dev_lock);
|
||||
if (idxd->sw_err.valid)
|
||||
@@ -407,6 +445,13 @@ static int idxd_user_drv_probe(struct idxd_dev *idxd_dev)
|
||||
}
|
||||
|
||||
mutex_lock(&wq->wq_lock);
|
||||
|
||||
wq->wq = create_workqueue(dev_name(wq_confdev(wq)));
|
||||
if (!wq->wq) {
|
||||
rc = -ENOMEM;
|
||||
goto wq_err;
|
||||
}
|
||||
|
||||
wq->type = IDXD_WQT_USER;
|
||||
rc = drv_enable_wq(wq);
|
||||
if (rc < 0)
|
||||
@@ -425,7 +470,9 @@ static int idxd_user_drv_probe(struct idxd_dev *idxd_dev)
|
||||
err_cdev:
|
||||
drv_disable_wq(wq);
|
||||
err:
|
||||
destroy_workqueue(wq->wq);
|
||||
wq->type = IDXD_WQT_NONE;
|
||||
wq_err:
|
||||
mutex_unlock(&wq->wq_lock);
|
||||
return rc;
|
||||
}
|
||||
@@ -438,6 +485,8 @@ static void idxd_user_drv_remove(struct idxd_dev *idxd_dev)
|
||||
idxd_wq_del_cdev(wq);
|
||||
drv_disable_wq(wq);
|
||||
wq->type = IDXD_WQT_NONE;
|
||||
destroy_workqueue(wq->wq);
|
||||
wq->wq = NULL;
|
||||
mutex_unlock(&wq->wq_lock);
|
||||
}
|
||||
|
||||
@@ -484,3 +533,70 @@ void idxd_cdev_remove(void)
|
||||
ida_destroy(&ictx[i].minor_ida);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* idxd_copy_cr - copy completion record to user address space found by wq and
|
||||
* PASID
|
||||
* @wq: work queue
|
||||
* @pasid: PASID
|
||||
* @addr: user fault address to write
|
||||
* @cr: completion record
|
||||
* @len: number of bytes to copy
|
||||
*
|
||||
* This is called by a work that handles completion record fault.
|
||||
*
|
||||
* Return: number of bytes copied.
|
||||
*/
|
||||
int idxd_copy_cr(struct idxd_wq *wq, ioasid_t pasid, unsigned long addr,
|
||||
void *cr, int len)
|
||||
{
|
||||
struct device *dev = &wq->idxd->pdev->dev;
|
||||
int left = len, status_size = 1;
|
||||
struct idxd_user_context *ctx;
|
||||
struct mm_struct *mm;
|
||||
|
||||
mutex_lock(&wq->uc_lock);
|
||||
|
||||
ctx = xa_load(&wq->upasid_xa, pasid);
|
||||
if (!ctx) {
|
||||
dev_warn(dev, "No user context\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
mm = ctx->mm;
|
||||
/*
|
||||
* The completion record fault handling work is running in kernel
|
||||
* thread context. It temporarily switches to the mm to copy cr
|
||||
* to addr in the mm.
|
||||
*/
|
||||
kthread_use_mm(mm);
|
||||
left = copy_to_user((void __user *)addr + status_size, cr + status_size,
|
||||
len - status_size);
|
||||
/*
|
||||
* Copy status only after the rest of completion record is copied
|
||||
* successfully so that the user gets the complete completion record
|
||||
* when a non-zero status is polled.
|
||||
*/
|
||||
if (!left) {
|
||||
u8 status;
|
||||
|
||||
/*
|
||||
* Ensure that the completion record's status field is written
|
||||
* after the rest of the completion record has been written.
|
||||
* This ensures that the user receives the correct completion
|
||||
* record information once polling for a non-zero status.
|
||||
*/
|
||||
wmb();
|
||||
status = *(u8 *)cr;
|
||||
if (put_user(status, (u8 __user *)addr))
|
||||
left += status_size;
|
||||
} else {
|
||||
left += status_size;
|
||||
}
|
||||
kthread_unuse_mm(mm);
|
||||
|
||||
out:
|
||||
mutex_unlock(&wq->uc_lock);
|
||||
|
||||
return len - left;
|
||||
}
|
||||
|
||||
@@ -185,6 +185,7 @@ struct idxd_wq {
|
||||
struct idxd_dev idxd_dev;
|
||||
struct idxd_cdev *idxd_cdev;
|
||||
struct wait_queue_head err_queue;
|
||||
struct workqueue_struct *wq;
|
||||
struct idxd_device *idxd;
|
||||
int id;
|
||||
struct idxd_irq_entry ie;
|
||||
@@ -214,6 +215,10 @@ struct idxd_wq {
|
||||
char name[WQ_NAME_SIZE + 1];
|
||||
u64 max_xfer_bytes;
|
||||
u32 max_batch_size;
|
||||
|
||||
/* Lock to protect upasid_xa access. */
|
||||
struct mutex uc_lock;
|
||||
struct xarray upasid_xa;
|
||||
};
|
||||
|
||||
struct idxd_engine {
|
||||
@@ -665,6 +670,8 @@ void idxd_cdev_remove(void);
|
||||
int idxd_cdev_get_major(struct idxd_device *idxd);
|
||||
int idxd_wq_add_cdev(struct idxd_wq *wq);
|
||||
void idxd_wq_del_cdev(struct idxd_wq *wq);
|
||||
int idxd_copy_cr(struct idxd_wq *wq, ioasid_t pasid, unsigned long addr,
|
||||
void *buf, int len);
|
||||
|
||||
/* perfmon */
|
||||
#if IS_ENABLED(CONFIG_INTEL_IDXD_PERFMON)
|
||||
|
||||
@@ -140,6 +140,25 @@ static void idxd_cleanup_interrupts(struct idxd_device *idxd)
|
||||
pci_free_irq_vectors(pdev);
|
||||
}
|
||||
|
||||
static void idxd_clean_wqs(struct idxd_device *idxd)
|
||||
{
|
||||
struct idxd_wq *wq;
|
||||
struct device *conf_dev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < idxd->max_wqs; i++) {
|
||||
wq = idxd->wqs[i];
|
||||
if (idxd->hw.wq_cap.op_config)
|
||||
bitmap_free(wq->opcap_bmap);
|
||||
kfree(wq->wqcfg);
|
||||
conf_dev = wq_confdev(wq);
|
||||
put_device(conf_dev);
|
||||
kfree(wq);
|
||||
}
|
||||
bitmap_free(idxd->wq_enable_map);
|
||||
kfree(idxd->wqs);
|
||||
}
|
||||
|
||||
static int idxd_setup_wqs(struct idxd_device *idxd)
|
||||
{
|
||||
struct device *dev = &idxd->pdev->dev;
|
||||
@@ -154,8 +173,8 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
|
||||
|
||||
idxd->wq_enable_map = bitmap_zalloc_node(idxd->max_wqs, GFP_KERNEL, dev_to_node(dev));
|
||||
if (!idxd->wq_enable_map) {
|
||||
kfree(idxd->wqs);
|
||||
return -ENOMEM;
|
||||
rc = -ENOMEM;
|
||||
goto err_bitmap;
|
||||
}
|
||||
|
||||
for (i = 0; i < idxd->max_wqs; i++) {
|
||||
@@ -174,10 +193,8 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
|
||||
conf_dev->bus = &dsa_bus_type;
|
||||
conf_dev->type = &idxd_wq_device_type;
|
||||
rc = dev_set_name(conf_dev, "wq%d.%d", idxd->id, wq->id);
|
||||
if (rc < 0) {
|
||||
put_device(conf_dev);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
mutex_init(&wq->wq_lock);
|
||||
init_waitqueue_head(&wq->err_queue);
|
||||
@@ -188,7 +205,6 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
|
||||
wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES;
|
||||
wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev));
|
||||
if (!wq->wqcfg) {
|
||||
put_device(conf_dev);
|
||||
rc = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
@@ -196,26 +212,58 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
|
||||
if (idxd->hw.wq_cap.op_config) {
|
||||
wq->opcap_bmap = bitmap_zalloc(IDXD_MAX_OPCAP_BITS, GFP_KERNEL);
|
||||
if (!wq->opcap_bmap) {
|
||||
put_device(conf_dev);
|
||||
rc = -ENOMEM;
|
||||
goto err;
|
||||
goto err_opcap_bmap;
|
||||
}
|
||||
bitmap_copy(wq->opcap_bmap, idxd->opcap_bmap, IDXD_MAX_OPCAP_BITS);
|
||||
}
|
||||
mutex_init(&wq->uc_lock);
|
||||
xa_init(&wq->upasid_xa);
|
||||
idxd->wqs[i] = wq;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
err_opcap_bmap:
|
||||
kfree(wq->wqcfg);
|
||||
|
||||
err:
|
||||
put_device(conf_dev);
|
||||
kfree(wq);
|
||||
|
||||
while (--i >= 0) {
|
||||
wq = idxd->wqs[i];
|
||||
if (idxd->hw.wq_cap.op_config)
|
||||
bitmap_free(wq->opcap_bmap);
|
||||
kfree(wq->wqcfg);
|
||||
conf_dev = wq_confdev(wq);
|
||||
put_device(conf_dev);
|
||||
kfree(wq);
|
||||
|
||||
}
|
||||
bitmap_free(idxd->wq_enable_map);
|
||||
|
||||
err_bitmap:
|
||||
kfree(idxd->wqs);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void idxd_clean_engines(struct idxd_device *idxd)
|
||||
{
|
||||
struct idxd_engine *engine;
|
||||
struct device *conf_dev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < idxd->max_engines; i++) {
|
||||
engine = idxd->engines[i];
|
||||
conf_dev = engine_confdev(engine);
|
||||
put_device(conf_dev);
|
||||
kfree(engine);
|
||||
}
|
||||
kfree(idxd->engines);
|
||||
}
|
||||
|
||||
static int idxd_setup_engines(struct idxd_device *idxd)
|
||||
{
|
||||
struct idxd_engine *engine;
|
||||
@@ -246,6 +294,7 @@ static int idxd_setup_engines(struct idxd_device *idxd)
|
||||
rc = dev_set_name(conf_dev, "engine%d.%d", idxd->id, engine->id);
|
||||
if (rc < 0) {
|
||||
put_device(conf_dev);
|
||||
kfree(engine);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -259,10 +308,26 @@ static int idxd_setup_engines(struct idxd_device *idxd)
|
||||
engine = idxd->engines[i];
|
||||
conf_dev = engine_confdev(engine);
|
||||
put_device(conf_dev);
|
||||
kfree(engine);
|
||||
}
|
||||
kfree(idxd->engines);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void idxd_clean_groups(struct idxd_device *idxd)
|
||||
{
|
||||
struct idxd_group *group;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < idxd->max_groups; i++) {
|
||||
group = idxd->groups[i];
|
||||
put_device(group_confdev(group));
|
||||
kfree(group);
|
||||
}
|
||||
kfree(idxd->groups);
|
||||
}
|
||||
|
||||
static int idxd_setup_groups(struct idxd_device *idxd)
|
||||
{
|
||||
struct device *dev = &idxd->pdev->dev;
|
||||
@@ -293,6 +358,7 @@ static int idxd_setup_groups(struct idxd_device *idxd)
|
||||
rc = dev_set_name(conf_dev, "group%d.%d", idxd->id, group->id);
|
||||
if (rc < 0) {
|
||||
put_device(conf_dev);
|
||||
kfree(group);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -312,27 +378,25 @@ static int idxd_setup_groups(struct idxd_device *idxd)
|
||||
while (--i >= 0) {
|
||||
group = idxd->groups[i];
|
||||
put_device(group_confdev(group));
|
||||
kfree(group);
|
||||
}
|
||||
kfree(idxd->groups);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void idxd_cleanup_internals(struct idxd_device *idxd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < idxd->max_groups; i++)
|
||||
put_device(group_confdev(idxd->groups[i]));
|
||||
for (i = 0; i < idxd->max_engines; i++)
|
||||
put_device(engine_confdev(idxd->engines[i]));
|
||||
for (i = 0; i < idxd->max_wqs; i++)
|
||||
put_device(wq_confdev(idxd->wqs[i]));
|
||||
idxd_clean_groups(idxd);
|
||||
idxd_clean_engines(idxd);
|
||||
idxd_clean_wqs(idxd);
|
||||
destroy_workqueue(idxd->wq);
|
||||
}
|
||||
|
||||
static int idxd_setup_internals(struct idxd_device *idxd)
|
||||
{
|
||||
struct device *dev = &idxd->pdev->dev;
|
||||
int rc, i;
|
||||
int rc;
|
||||
|
||||
init_waitqueue_head(&idxd->cmd_waitq);
|
||||
|
||||
@@ -357,14 +421,11 @@ static int idxd_setup_internals(struct idxd_device *idxd)
|
||||
return 0;
|
||||
|
||||
err_wkq_create:
|
||||
for (i = 0; i < idxd->max_groups; i++)
|
||||
put_device(group_confdev(idxd->groups[i]));
|
||||
idxd_clean_groups(idxd);
|
||||
err_group:
|
||||
for (i = 0; i < idxd->max_engines; i++)
|
||||
put_device(engine_confdev(idxd->engines[i]));
|
||||
idxd_clean_engines(idxd);
|
||||
err_engine:
|
||||
for (i = 0; i < idxd->max_wqs; i++)
|
||||
put_device(wq_confdev(idxd->wqs[i]));
|
||||
idxd_clean_wqs(idxd);
|
||||
err_wqs:
|
||||
return rc;
|
||||
}
|
||||
@@ -460,6 +521,17 @@ static void idxd_read_caps(struct idxd_device *idxd)
|
||||
multi_u64_to_bmap(idxd->opcap_bmap, &idxd->hw.opcap.bits[0], 4);
|
||||
}
|
||||
|
||||
static void idxd_free(struct idxd_device *idxd)
|
||||
{
|
||||
if (!idxd)
|
||||
return;
|
||||
|
||||
put_device(idxd_confdev(idxd));
|
||||
bitmap_free(idxd->opcap_bmap);
|
||||
ida_free(&idxd_ida, idxd->id);
|
||||
kfree(idxd);
|
||||
}
|
||||
|
||||
static struct idxd_device *idxd_alloc(struct pci_dev *pdev, struct idxd_driver_data *data)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -477,28 +549,34 @@ static struct idxd_device *idxd_alloc(struct pci_dev *pdev, struct idxd_driver_d
|
||||
idxd_dev_set_type(&idxd->idxd_dev, idxd->data->type);
|
||||
idxd->id = ida_alloc(&idxd_ida, GFP_KERNEL);
|
||||
if (idxd->id < 0)
|
||||
return NULL;
|
||||
goto err_ida;
|
||||
|
||||
idxd->opcap_bmap = bitmap_zalloc_node(IDXD_MAX_OPCAP_BITS, GFP_KERNEL, dev_to_node(dev));
|
||||
if (!idxd->opcap_bmap) {
|
||||
ida_free(&idxd_ida, idxd->id);
|
||||
return NULL;
|
||||
}
|
||||
if (!idxd->opcap_bmap)
|
||||
goto err_opcap;
|
||||
|
||||
device_initialize(conf_dev);
|
||||
conf_dev->parent = dev;
|
||||
conf_dev->bus = &dsa_bus_type;
|
||||
conf_dev->type = idxd->data->dev_type;
|
||||
rc = dev_set_name(conf_dev, "%s%d", idxd->data->name_prefix, idxd->id);
|
||||
if (rc < 0) {
|
||||
put_device(conf_dev);
|
||||
return NULL;
|
||||
}
|
||||
if (rc < 0)
|
||||
goto err_name;
|
||||
|
||||
spin_lock_init(&idxd->dev_lock);
|
||||
spin_lock_init(&idxd->cmd_lock);
|
||||
|
||||
return idxd;
|
||||
|
||||
err_name:
|
||||
put_device(conf_dev);
|
||||
bitmap_free(idxd->opcap_bmap);
|
||||
err_opcap:
|
||||
ida_free(&idxd_ida, idxd->id);
|
||||
err_ida:
|
||||
kfree(idxd);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int idxd_enable_system_pasid(struct idxd_device *idxd)
|
||||
@@ -651,7 +729,7 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
err:
|
||||
pci_iounmap(pdev, idxd->reg_base);
|
||||
err_iomap:
|
||||
put_device(idxd_confdev(idxd));
|
||||
idxd_free(idxd);
|
||||
err_idxd_alloc:
|
||||
pci_disable_device(pdev);
|
||||
return rc;
|
||||
@@ -714,6 +792,7 @@ static void idxd_remove(struct pci_dev *pdev)
|
||||
destroy_workqueue(idxd->wq);
|
||||
perfmon_pmu_remove(idxd);
|
||||
put_device(idxd_confdev(idxd));
|
||||
idxd_free(idxd);
|
||||
}
|
||||
|
||||
static struct pci_driver idxd_pci_driver = {
|
||||
|
||||
@@ -1315,6 +1315,7 @@ static void idxd_conf_wq_release(struct device *dev)
|
||||
|
||||
bitmap_free(wq->opcap_bmap);
|
||||
kfree(wq->wqcfg);
|
||||
xa_destroy(&wq->upasid_xa);
|
||||
kfree(wq);
|
||||
}
|
||||
|
||||
|
||||
@@ -1088,8 +1088,11 @@ static void udma_check_tx_completion(struct work_struct *work)
|
||||
u32 residue_diff;
|
||||
ktime_t time_diff;
|
||||
unsigned long delay;
|
||||
unsigned long flags;
|
||||
|
||||
while (1) {
|
||||
spin_lock_irqsave(&uc->vc.lock, flags);
|
||||
|
||||
if (uc->desc) {
|
||||
/* Get previous residue and time stamp */
|
||||
residue_diff = uc->tx_drain.residue;
|
||||
@@ -1124,6 +1127,8 @@ static void udma_check_tx_completion(struct work_struct *work)
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&uc->vc.lock, flags);
|
||||
|
||||
usleep_range(ktime_to_us(delay),
|
||||
ktime_to_us(delay) + 10);
|
||||
continue;
|
||||
@@ -1140,6 +1145,8 @@ static void udma_check_tx_completion(struct work_struct *work)
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&uc->vc.lock, flags);
|
||||
}
|
||||
|
||||
static irqreturn_t udma_ring_irq_handler(int irq, void *data)
|
||||
@@ -4209,7 +4216,6 @@ static struct dma_chan *udma_of_xlate(struct of_phandle_args *dma_spec,
|
||||
struct of_dma *ofdma)
|
||||
{
|
||||
struct udma_dev *ud = ofdma->of_dma_data;
|
||||
dma_cap_mask_t mask = ud->ddev.cap_mask;
|
||||
struct udma_filter_param filter_param;
|
||||
struct dma_chan *chan;
|
||||
|
||||
@@ -4241,7 +4247,7 @@ static struct dma_chan *udma_of_xlate(struct of_phandle_args *dma_spec,
|
||||
}
|
||||
}
|
||||
|
||||
chan = __dma_request_channel(&mask, udma_dma_filter_fn, &filter_param,
|
||||
chan = __dma_request_channel(&ud->ddev.cap_mask, udma_dma_filter_fn, &filter_param,
|
||||
ofdma->of_node);
|
||||
if (!chan) {
|
||||
dev_err(ud->dev, "get channel fail in %s.\n", __func__);
|
||||
|
||||
@@ -405,10 +405,9 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx)
|
||||
int i, j, ret;
|
||||
struct mem_ctl_info *mci = NULL;
|
||||
struct edac_mc_layer layers[2];
|
||||
struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL];
|
||||
void __iomem *window;
|
||||
struct ie31200_priv *priv;
|
||||
u32 addr_decode, mad_offset;
|
||||
u32 addr_decode[IE31200_CHANNELS], mad_offset;
|
||||
|
||||
/*
|
||||
* Kaby Lake, Coffee Lake seem to work like Skylake. Please re-visit
|
||||
@@ -466,19 +465,10 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx)
|
||||
mad_offset = IE31200_MAD_DIMM_0_OFFSET;
|
||||
}
|
||||
|
||||
/* populate DIMM info */
|
||||
for (i = 0; i < IE31200_CHANNELS; i++) {
|
||||
addr_decode = readl(window + mad_offset +
|
||||
addr_decode[i] = readl(window + mad_offset +
|
||||
(i * 4));
|
||||
edac_dbg(0, "addr_decode: 0x%x\n", addr_decode);
|
||||
for (j = 0; j < IE31200_DIMMS_PER_CHANNEL; j++) {
|
||||
populate_dimm_info(&dimm_info[i][j], addr_decode, j,
|
||||
skl);
|
||||
edac_dbg(0, "size: 0x%x, rank: %d, width: %d\n",
|
||||
dimm_info[i][j].size,
|
||||
dimm_info[i][j].dual_rank,
|
||||
dimm_info[i][j].x16_width);
|
||||
}
|
||||
edac_dbg(0, "addr_decode: 0x%x\n", addr_decode[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -489,14 +479,22 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx)
|
||||
*/
|
||||
for (i = 0; i < IE31200_DIMMS_PER_CHANNEL; i++) {
|
||||
for (j = 0; j < IE31200_CHANNELS; j++) {
|
||||
struct dimm_data dimm_info;
|
||||
struct dimm_info *dimm;
|
||||
unsigned long nr_pages;
|
||||
|
||||
nr_pages = IE31200_PAGES(dimm_info[j][i].size, skl);
|
||||
populate_dimm_info(&dimm_info, addr_decode[j], i,
|
||||
skl);
|
||||
edac_dbg(0, "size: 0x%x, rank: %d, width: %d\n",
|
||||
dimm_info.size,
|
||||
dimm_info.dual_rank,
|
||||
dimm_info.x16_width);
|
||||
|
||||
nr_pages = IE31200_PAGES(dimm_info.size, skl);
|
||||
if (nr_pages == 0)
|
||||
continue;
|
||||
|
||||
if (dimm_info[j][i].dual_rank) {
|
||||
if (dimm_info.dual_rank) {
|
||||
nr_pages = nr_pages / 2;
|
||||
dimm = edac_get_dimm(mci, (i * 2) + 1, j, 0);
|
||||
dimm->nr_pages = nr_pages;
|
||||
|
||||
@@ -191,6 +191,7 @@ struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
|
||||
dev = &ffa_dev->dev;
|
||||
dev->bus = &ffa_bus_type;
|
||||
dev->release = ffa_release_device;
|
||||
dev->dma_mask = &dev->coherent_dma_mask;
|
||||
dev_set_name(&ffa_dev->dev, "arm-ffa-%d", id);
|
||||
|
||||
ffa_dev->id = id;
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
/* V2 Defines */
|
||||
#define VSE_CVP_TX_CREDITS 0x49 /* 8bit */
|
||||
|
||||
#define V2_CREDIT_TIMEOUT_US 20000
|
||||
#define V2_CREDIT_TIMEOUT_US 40000
|
||||
#define V2_CHECK_CREDIT_US 10
|
||||
#define V2_POLL_TIMEOUT_US 1000000
|
||||
#define V2_USER_TIMEOUT_US 500000
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
@@ -20,6 +21,7 @@
|
||||
#include <linux/platform_data/pca953x.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
@@ -522,12 +524,10 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
|
||||
struct pca953x_chip *chip = gpiochip_get_data(gc);
|
||||
u8 dirreg = chip->recalc_addr(chip, chip->regs->direction, off);
|
||||
u8 bit = BIT(off % BANK_SZ);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&chip->i2c_lock);
|
||||
ret = regmap_write_bits(chip->regmap, dirreg, bit, bit);
|
||||
mutex_unlock(&chip->i2c_lock);
|
||||
return ret;
|
||||
guard(mutex)(&chip->i2c_lock);
|
||||
|
||||
return regmap_write_bits(chip->regmap, dirreg, bit, bit);
|
||||
}
|
||||
|
||||
static int pca953x_gpio_direction_output(struct gpio_chip *gc,
|
||||
@@ -539,17 +539,15 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
|
||||
u8 bit = BIT(off % BANK_SZ);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&chip->i2c_lock);
|
||||
guard(mutex)(&chip->i2c_lock);
|
||||
|
||||
/* set output level */
|
||||
ret = regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0);
|
||||
if (ret)
|
||||
goto exit;
|
||||
return ret;
|
||||
|
||||
/* then direction */
|
||||
ret = regmap_write_bits(chip->regmap, dirreg, bit, 0);
|
||||
exit:
|
||||
mutex_unlock(&chip->i2c_lock);
|
||||
return ret;
|
||||
return regmap_write_bits(chip->regmap, dirreg, bit, 0);
|
||||
}
|
||||
|
||||
static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
|
||||
@@ -560,9 +558,8 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
|
||||
u32 reg_val;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&chip->i2c_lock);
|
||||
ret = regmap_read(chip->regmap, inreg, ®_val);
|
||||
mutex_unlock(&chip->i2c_lock);
|
||||
scoped_guard(mutex, &chip->i2c_lock)
|
||||
ret = regmap_read(chip->regmap, inreg, ®_val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -575,9 +572,9 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
|
||||
u8 outreg = chip->recalc_addr(chip, chip->regs->output, off);
|
||||
u8 bit = BIT(off % BANK_SZ);
|
||||
|
||||
mutex_lock(&chip->i2c_lock);
|
||||
guard(mutex)(&chip->i2c_lock);
|
||||
|
||||
regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0);
|
||||
mutex_unlock(&chip->i2c_lock);
|
||||
}
|
||||
|
||||
static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off)
|
||||
@@ -588,9 +585,8 @@ static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off)
|
||||
u32 reg_val;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&chip->i2c_lock);
|
||||
ret = regmap_read(chip->regmap, dirreg, ®_val);
|
||||
mutex_unlock(&chip->i2c_lock);
|
||||
scoped_guard(mutex, &chip->i2c_lock)
|
||||
ret = regmap_read(chip->regmap, dirreg, ®_val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -607,9 +603,8 @@ static int pca953x_gpio_get_multiple(struct gpio_chip *gc,
|
||||
DECLARE_BITMAP(reg_val, MAX_LINE);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&chip->i2c_lock);
|
||||
ret = pca953x_read_regs(chip, chip->regs->input, reg_val);
|
||||
mutex_unlock(&chip->i2c_lock);
|
||||
scoped_guard(mutex, &chip->i2c_lock)
|
||||
ret = pca953x_read_regs(chip, chip->regs->input, reg_val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -624,16 +619,15 @@ static void pca953x_gpio_set_multiple(struct gpio_chip *gc,
|
||||
DECLARE_BITMAP(reg_val, MAX_LINE);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&chip->i2c_lock);
|
||||
guard(mutex)(&chip->i2c_lock);
|
||||
|
||||
ret = pca953x_read_regs(chip, chip->regs->output, reg_val);
|
||||
if (ret)
|
||||
goto exit;
|
||||
return;
|
||||
|
||||
bitmap_replace(reg_val, reg_val, bits, mask, gc->ngpio);
|
||||
|
||||
pca953x_write_regs(chip, chip->regs->output, reg_val);
|
||||
exit:
|
||||
mutex_unlock(&chip->i2c_lock);
|
||||
}
|
||||
|
||||
static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip,
|
||||
@@ -641,7 +635,6 @@ static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip,
|
||||
unsigned long config)
|
||||
{
|
||||
enum pin_config_param param = pinconf_to_config_param(config);
|
||||
|
||||
u8 pull_en_reg = chip->recalc_addr(chip, PCAL953X_PULL_EN, offset);
|
||||
u8 pull_sel_reg = chip->recalc_addr(chip, PCAL953X_PULL_SEL, offset);
|
||||
u8 bit = BIT(offset % BANK_SZ);
|
||||
@@ -654,7 +647,7 @@ static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip,
|
||||
if (!(chip->driver_data & PCA_PCAL))
|
||||
return -ENOTSUPP;
|
||||
|
||||
mutex_lock(&chip->i2c_lock);
|
||||
guard(mutex)(&chip->i2c_lock);
|
||||
|
||||
/* Configure pull-up/pull-down */
|
||||
if (param == PIN_CONFIG_BIAS_PULL_UP)
|
||||
@@ -664,17 +657,13 @@ static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip,
|
||||
else
|
||||
ret = 0;
|
||||
if (ret)
|
||||
goto exit;
|
||||
return ret;
|
||||
|
||||
/* Disable/Enable pull-up/pull-down */
|
||||
if (param == PIN_CONFIG_BIAS_DISABLE)
|
||||
ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, 0);
|
||||
return regmap_write_bits(chip->regmap, pull_en_reg, bit, 0);
|
||||
else
|
||||
ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, bit);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&chip->i2c_lock);
|
||||
return ret;
|
||||
return regmap_write_bits(chip->regmap, pull_en_reg, bit, bit);
|
||||
}
|
||||
|
||||
static int pca953x_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
|
||||
@@ -887,10 +876,8 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
|
||||
|
||||
bitmap_zero(pending, MAX_LINE);
|
||||
|
||||
mutex_lock(&chip->i2c_lock);
|
||||
ret = pca953x_irq_pending(chip, pending);
|
||||
mutex_unlock(&chip->i2c_lock);
|
||||
|
||||
scoped_guard(mutex, &chip->i2c_lock)
|
||||
ret = pca953x_irq_pending(chip, pending);
|
||||
if (ret) {
|
||||
ret = 0;
|
||||
|
||||
@@ -1199,9 +1186,9 @@ static void pca953x_remove(struct i2c_client *client)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int pca953x_regcache_sync(struct device *dev)
|
||||
static int pca953x_regcache_sync(struct pca953x_chip *chip)
|
||||
{
|
||||
struct pca953x_chip *chip = dev_get_drvdata(dev);
|
||||
struct device *dev = &chip->client->dev;
|
||||
int ret;
|
||||
u8 regaddr;
|
||||
|
||||
@@ -1248,13 +1235,38 @@ static int pca953x_regcache_sync(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pca953x_restore_context(struct pca953x_chip *chip)
|
||||
{
|
||||
int ret;
|
||||
|
||||
guard(mutex)(&chip->i2c_lock);
|
||||
|
||||
if (chip->client->irq > 0)
|
||||
enable_irq(chip->client->irq);
|
||||
regcache_cache_only(chip->regmap, false);
|
||||
regcache_mark_dirty(chip->regmap);
|
||||
ret = pca953x_regcache_sync(chip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return regcache_sync(chip->regmap);
|
||||
}
|
||||
|
||||
static void pca953x_save_context(struct pca953x_chip *chip)
|
||||
{
|
||||
guard(mutex)(&chip->i2c_lock);
|
||||
|
||||
/* Disable IRQ to prevent early triggering while regmap "cache only" is on */
|
||||
if (chip->client->irq > 0)
|
||||
disable_irq(chip->client->irq);
|
||||
regcache_cache_only(chip->regmap, true);
|
||||
}
|
||||
|
||||
static int pca953x_suspend(struct device *dev)
|
||||
{
|
||||
struct pca953x_chip *chip = dev_get_drvdata(dev);
|
||||
|
||||
mutex_lock(&chip->i2c_lock);
|
||||
regcache_cache_only(chip->regmap, true);
|
||||
mutex_unlock(&chip->i2c_lock);
|
||||
pca953x_save_context(chip);
|
||||
|
||||
if (atomic_read(&chip->wakeup_path))
|
||||
device_set_wakeup_path(dev);
|
||||
@@ -1277,17 +1289,7 @@ static int pca953x_resume(struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&chip->i2c_lock);
|
||||
regcache_cache_only(chip->regmap, false);
|
||||
regcache_mark_dirty(chip->regmap);
|
||||
ret = pca953x_regcache_sync(dev);
|
||||
if (ret) {
|
||||
mutex_unlock(&chip->i2c_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regcache_sync(chip->regmap);
|
||||
mutex_unlock(&chip->i2c_lock);
|
||||
ret = pca953x_restore_context(chip);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to restore register map: %d\n", ret);
|
||||
return ret;
|
||||
|
||||
@@ -781,6 +781,7 @@ struct amdgpu_device {
|
||||
bool need_swiotlb;
|
||||
bool accel_working;
|
||||
struct notifier_block acpi_nb;
|
||||
struct notifier_block pm_nb;
|
||||
struct amdgpu_i2c_chan *i2c_bus[AMDGPU_MAX_I2C_BUS];
|
||||
struct debugfs_blob_wrapper debugfs_vbios_blob;
|
||||
struct debugfs_blob_wrapper debugfs_discovery_blob;
|
||||
|
||||
@@ -139,6 +139,10 @@ const char *amdgpu_asic_name[] = {
|
||||
"LAST",
|
||||
};
|
||||
|
||||
static inline void amdgpu_device_stop_pending_resets(struct amdgpu_device *adev);
|
||||
static int amdgpu_device_pm_notifier(struct notifier_block *nb, unsigned long mode,
|
||||
void *data);
|
||||
|
||||
/**
|
||||
* DOC: pcie_replay_count
|
||||
*
|
||||
@@ -3990,6 +3994,11 @@ fence_driver_init:
|
||||
|
||||
amdgpu_device_check_iommu_direct_map(adev);
|
||||
|
||||
adev->pm_nb.notifier_call = amdgpu_device_pm_notifier;
|
||||
r = register_pm_notifier(&adev->pm_nb);
|
||||
if (r)
|
||||
goto failed;
|
||||
|
||||
return 0;
|
||||
|
||||
release_ras_con:
|
||||
@@ -4051,6 +4060,8 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
|
||||
flush_delayed_work(&adev->delayed_init_work);
|
||||
adev->shutdown = true;
|
||||
|
||||
unregister_pm_notifier(&adev->pm_nb);
|
||||
|
||||
/* make sure IB test finished before entering exclusive mode
|
||||
* to avoid preemption on IB test
|
||||
* */
|
||||
@@ -4181,6 +4192,33 @@ static int amdgpu_device_evict_resources(struct amdgpu_device *adev)
|
||||
/*
|
||||
* Suspend & resume.
|
||||
*/
|
||||
/**
|
||||
* amdgpu_device_pm_notifier - Notification block for Suspend/Hibernate events
|
||||
* @nb: notifier block
|
||||
* @mode: suspend mode
|
||||
* @data: data
|
||||
*
|
||||
* This function is called when the system is about to suspend or hibernate.
|
||||
* It is used to set the appropriate flags so that eviction can be optimized
|
||||
* in the pm prepare callback.
|
||||
*/
|
||||
static int amdgpu_device_pm_notifier(struct notifier_block *nb, unsigned long mode,
|
||||
void *data)
|
||||
{
|
||||
struct amdgpu_device *adev = container_of(nb, struct amdgpu_device, pm_nb);
|
||||
|
||||
switch (mode) {
|
||||
case PM_HIBERNATION_PREPARE:
|
||||
adev->in_s4 = true;
|
||||
break;
|
||||
case PM_POST_HIBERNATION:
|
||||
adev->in_s4 = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_prepare - prepare for device suspend
|
||||
*
|
||||
@@ -4631,6 +4669,8 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
|
||||
retry:
|
||||
amdgpu_amdkfd_pre_reset(adev);
|
||||
|
||||
amdgpu_device_stop_pending_resets(adev);
|
||||
|
||||
if (from_hypervisor)
|
||||
r = amdgpu_virt_request_full_gpu(adev, true);
|
||||
else
|
||||
@@ -5502,11 +5542,12 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */
|
||||
tmp_adev->asic_reset_res = r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop all pending non scheduler resets. Scheduler resets
|
||||
* were already dropped during drm_sched_stop
|
||||
*/
|
||||
amdgpu_device_stop_pending_resets(tmp_adev);
|
||||
if (!amdgpu_sriov_vf(tmp_adev))
|
||||
/*
|
||||
* Drop all pending non scheduler resets. Scheduler resets
|
||||
* were already dropped during drm_sched_stop
|
||||
*/
|
||||
amdgpu_device_stop_pending_resets(tmp_adev);
|
||||
}
|
||||
|
||||
tmp_vram_lost_counter = atomic_read(&((adev)->vram_lost_counter));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user