https://source.android.com/docs/security/bulletin/2023-09-01 * tag 'ASB-2023-09-05_4.14-stable' of https://android.googlesource.com/kernel/common: Linux 4.14.325 Revert "ARM: ep93xx: fix missing-prototype warnings" Revert "MIPS: Alchemy: fix dbdma2" Linux 4.14.324 dma-buf/sw_sync: Avoid recursive lock during fence signal scsi: core: raid_class: Remove raid_component_add() scsi: snic: Fix double free in snic_tgt_create() rtnetlink: Reject negative ifindexes in RTM_NEWLINK x86/fpu: Set X86_FEATURE_OSXSAVE feature after enabling OSXSAVE in CR4 media: vcodec: Fix potential array out-of-bounds in encoder queue_setup lib/clz_ctz.c: Fix __clzdi2() and __ctzdi2() for 32-bit kernels batman-adv: Fix batadv_v_ogm_aggr_send memory leak batman-adv: Fix TT global entry leak when client roamed back batman-adv: Do not get eth header before batadv_check_management_packet batman-adv: Trigger events for auto adjusted MTU ibmveth: Use dcbf rather than dcbfl ipvs: fix racy memcpy in proc_do_sync_threshold ipvs: Improve robustness to the ipvs sysctl igb: Avoid starting unnecessary workqueues sock: annotate data-races around prot->memory_pressure tracing: Fix memleak due to race between current_tracer and trace net: phy: broadcom: stub c45 read/write for 54810 net: xfrm: Amend XFRMA_SEC_CTX nla_policy structure net: fix the RTO timer retransmitting skb every 1ms if linear option is enabled af_unix: Fix null-ptr-deref in unix_stream_sendpage(). ASoC: rt5665: add missed regulator_bulk_disable netfilter: set default timeout to 3 secs for sctp shutdown send and recv state test_firmware: prevent race conditions by a correct implementation of locking binder: fix memory leak in binder_init() serial: 8250: Fix oops for port->pm on uart_change_pm() mmc: wbsd: fix double mmc_free_host() in wbsd_init() cifs: Release folio lock on fscache read hit. ALSA: usb-audio: Add support for Mythware XA001AU capture and playback interfaces. net: do not allow gso_size to be set to GSO_BY_FRAGS sock: Fix misuse of sk_under_memory_pressure() i40e: fix misleading debug logs team: Fix incorrect deletion of ETH_P_8021AD protocol vid from slaves netfilter: nft_dynset: disallow object maps xfrm: add NULL check in xfrm_update_ae_params ip_vti: fix potential slab-use-after-free in decode_session6 ip6_vti: fix slab-use-after-free in decode_session6 net: af_key: fix sadb_x_filter validation net: xfrm: Fix xfrm_address_filter OOB read fbdev: mmp: fix value check in mmphw_probe() drm/amdgpu: Fix potential fence use-after-free v2 Bluetooth: L2CAP: Fix use-after-free pcmcia: rsrc_nonstatic: Fix memory leak in nonstatic_release_resource_db() gfs2: Fix possible data races in gfs2_show_options() media: platform: mediatek: vpu: fix NULL ptr dereference media: v4l2-mem2mem: add lock to protect parameter num_rdy FS: JFS: Check for read-only mounted filesystem in txBegin FS: JFS: Fix null-ptr-deref Read in txBegin MIPS: dec: prom: Address -Warray-bounds warning fs: jfs: Fix UBSAN: array-index-out-of-bounds in dbAllocDmapLev udf: Fix uninitialized array access for some pathnames quota: fix warning in dqgrab() quota: Properly disable quotas when add_dquot_ref() fails ALSA: emu10k1: roll up loops in DSP setup code for Audigy drm/radeon: Fix integer overflow in radeon_cs_parser_init lib/mpi: Eliminate unused umul_ppmm definitions for MIPS UPSTREAM: media: usb: siano: Fix warning due to null work_func_t function pointer UPSTREAM: Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_ready_cb UPSTREAM: net/sched: cls_route: No longer copy tcf_result on update to avoid use-after-free UPSTREAM: net/sched: cls_fw: Fix improper refcount update leads to use-after-free UPSTREAM: net/sched: cls_u32: No longer copy tcf_result on update to avoid use-after-free Linux 4.14.323 alpha: remove __init annotation from exported page_is_ram() scsi: core: Fix possible memory leak if device_add() fails scsi: snic: Fix possible memory leak if device_add() fails scsi: 53c700: Check that command slot is not NULL scsi: storvsc: Fix handling of virtual Fibre Channel timeouts scsi: core: Fix legacy /proc parsing buffer overflow netfilter: nf_tables: report use refcount overflow btrfs: don't stop integrity writeback too early IB/hfi1: Fix possible panic during hotplug remove drivers: net: prevent tun_build_skb() to exceed the packet size limit dccp: fix data-race around dp->dccps_mss_cache bonding: Fix incorrect deletion of ETH_P_8021AD protocol vid from slaves net/packet: annotate data-races around tp->status drm/nouveau/disp: Revert a NULL check inside nouveau_connector_get_modes x86: Move gds_ucode_mitigated() declaration to header x86/mm: Fix VDSO and VVAR placement on 5-level paging machines usb: dwc3: Properly handle processing of pending events usb-storage: alauda: Fix uninit-value in alauda_check_media() iio: cros_ec: Fix the allocation size for cros_ec_command test_firmware: return ENOMEM instead of ENOSPC on failed memory allocation nilfs2: fix use-after-free of nilfs_root in dirtying inodes via iput radix tree test suite: fix incorrect allocation size for pthreads dmaengine: pl330: Return DMA_PAUSED when transaction is paused ipv6: adjust ndisc_is_useropt() to also return true for PIO mmc: moxart: read scr register without changing byte order sparc: fix up arch_cpu_finalize_init() build breakage. Linux 4.14.322 drm/edid: fix objtool warning in drm_cvt_modes() mtd: rawnand: omap_elm: Fix incorrect type in assignment test_firmware: fix a memory leak with reqs buffer ext2: Drop fragment support net: usbnet: Fix WARNING in usbnet_start_xmit/usb_submit_urb Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_ready_cb fs/sysv: Null check to prevent null-ptr-deref bug USB: zaurus: Add ID for A-300/B-500/C-700 libceph: fix potential hang in ceph_osdc_notify() loop: Select I/O scheduler 'none' from inside add_disk() tcp_metrics: fix data-race in tcpm_suck_dst() vs fastopen tcp_metrics: annotate data-races around tm->tcpm_net tcp_metrics: annotate data-races around tm->tcpm_vals[] tcp_metrics: annotate data-races around tm->tcpm_lock tcp_metrics: annotate data-races around tm->tcpm_stamp tcp_metrics: fix addr_same() helper ip6mr: Fix skb_under_panic in ip6mr_cache_report() net/sched: cls_route: No longer copy tcf_result on update to avoid use-after-free net/sched: cls_u32: No longer copy tcf_result on update to avoid use-after-free net: add missing data-race annotation for sk_ll_usec net: add missing data-race annotations around sk->sk_peek_off perf test uprobe_from_different_cu: Skip if there is no gcc net/mlx5e: fix return value check in mlx5e_ipsec_remove_trailer() word-at-a-time: use the same return type for has_zero regardless of endianness perf: Fix function pointer case net/sched: cls_u32: Fix reference counter leak leading to overflow net/sched: sch_qfq: account for stab overhead in qfq_enqueue net/sched: cls_fw: Fix improper refcount update leads to use-after-free drm/client: Fix memory leak in drm_client_target_cloned dm cache policy smq: ensure IO doesn't prevent cleaner policy progress ASoC: wm8904: Fill the cache for WM8904_ADC_TEST_0 register s390/dasd: fix hanging device after quiesce/resume irq-bcm6345-l1: Do not assume a fixed block to cpu mapping tpm_tis: Explicitly check for error code hwmon: (nct7802) Fix for temp6 (PECI1) processed even if PECI1 disabled staging: ks7010: potential buffer overflow in ks_wlan_set_encode_ext() Documentation: security-bugs.rst: update preferences when dealing with the linux-distros group usb: xhci-mtk: set the dma max_seg_size usb: ohci-at91: Fix the unhandle interrupt when resume can: gs_usb: gs_can_close(): add missing set of CAN state to CAN_STATE_STOPPED USB: serial: simple: sort driver entries USB: serial: simple: add Kaufmann RKS+CAN VCP USB: serial: option: add Quectel EC200A module support USB: serial: option: support Quectel EM060K_128 tracing: Fix warning in trace_buffered_event_disable() ring-buffer: Fix wrong stat of cpu_buffer->read ata: pata_ns87415: mark ns87560_tf_read static dm raid: fix missing reconfig_mutex unlock in raid_ctr() error paths block: Fix a source code comment in include/uapi/linux/blkzoned.h ASoC: fsl_spdif: Silence output on stop benet: fix return value check in be_lancer_xmit_workarounds() platform/x86: msi-laptop: Fix rfkill out-of-sync on MSI Wind U100 team: reset team's flags when down link is P2P device bonding: reset bond's flags when down link is P2P device tcp: Reduce chance of collisions in inet6_hashfn(). ipv6 addrconf: fix bug where deleting a mngtmpaddr can create a new temporary address ethernet: atheros: fix return value check in atl1e_tso_csum() i40e: Fix an NULL vs IS_ERR() bug for debugfs_create_dir() gpio: tps68470: Make tps68470_gpio_output() always set the initial value tcp: annotate data-races around fastopenq.max_qlen tcp: annotate data-races around tp->notsent_lowat tcp: annotate data-races around rskq_defer_accept netfilter: nf_tables: fix spurious set element insertion failure llc: Don't drop packet from non-root netns. fbdev: au1200fb: Fix missing IRQ check in au1200fb_drv_probe net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()/cpsw_ale_set_field() pinctrl: amd: Use amd_pinconf_set() for all config options fbdev: imxfb: warn about invalid left/right margin spi: bcm63xx: fix max prepend length igb: Fix igb_down hung on surprise removal wifi: wext-core: Fix -Wstringop-overflow warning in ioctl_standard_iw_point() bpf: Address KCSAN report on bpf_lru_list sched/fair: Don't balance task to its current running CPU posix-timers: Ensure timer ID search-loop limit is valid md/raid10: prevent soft lockup while flush writes md: fix data corruption for raid456 when reshape restart while grow up nbd: Add the maximum limit of allocated index in nbd_dev_add debugobjects: Recheck debug_objects_enabled before reporting ext4: correct inline offset when handling xattrs in inode body can: bcm: Fix UAF in bcm_proc_show() fuse: revalidate: don't invalidate if interrupted perf probe: Add test for regression introduced by switch to die_get_decl_file() serial: atmel: don't enable IRQs prematurely scsi: qla2xxx: Pointer may be dereferenced scsi: qla2xxx: Check valid rport returned by fc_bsg_to_rport() scsi: qla2xxx: Fix potential NULL pointer dereference scsi: qla2xxx: Wait for io return on terminate rport xtensa: ISS: fix call to split_if_spec ring-buffer: Fix deadloop issue on reading trace_pipe tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() when iterating clk tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() in case of error Revert "8250: add support for ASIX devices with a FIFO bug" meson saradc: fix clock divider mask length hwrng: imx-rngc - fix the timeout for init and self check fs: dlm: return positive pid value for F_GETLK md/raid0: add discard support for the 'original' layout misc: pci_endpoint_test: Re-init completion for every test PCI: Add function 1 DMA alias quirk for Marvell 88SE9235 jfs: jfs_dmap: Validate db_l2nbperpage while mounting ext4: only update i_reserved_data_blocks on successful block allocation ext4: fix wrong unit use in ext4_mb_clear_bb perf intel-pt: Fix CYC timestamps after standalone CBR SUNRPC: Fix UAF in svc_tcp_listen_data_ready() tpm: tpm_vtpm_proxy: fix a race condition in /dev/vtpmx creation net/sched: make psched_mtu() RTNL-less safe wifi: airo: avoid uninitialized warning in airo_get_rate() ipv6/addrconf: fix a potential refcount underflow for idev NTB: ntb_transport: fix possible memory leak while device_register() fails ntb: intel: Fix error handling in intel_ntb_pci_driver_init() NTB: amd: Fix error handling in amd_ntb_pci_driver_init() ntb: idt: Fix error handling in idt_pci_driver_init() udp6: fix udp6_ehashfn() typo net: mvneta: fix txq_map in case of txq_number==1 workqueue: clean up WORK_* constant types, clarify masking netfilter: nf_tables: prevent OOB access in nft_byteorder_eval netfilter: conntrack: Avoid nf_ct_helper_hash uses after free netfilter: nf_tables: unbind non-anonymous set if rule construction fails netfilter: nf_tables: add NFT_TRANS_PREPARE_ERROR to deal with bound set/chain netfilter: nf_tables: incorrect error path handling with NFT_MSG_NEWRULE spi: spi-fsl-spi: allow changing bits_per_word while CS is still active spi: spi-fsl-spi: relax message sanity checking a little spi: spi-fsl-spi: remove always-true conditional in fsl_spi_do_one_msg ARM: orion5x: fix d2net gpio initialization btrfs: fix race when deleting quota root from the dirty cow roots list jffs2: reduce stack usage in jffs2_build_xattr_subsystem() integrity: Fix possible multiple allocation in integrity_inode_get() mmc: core: disable TRIM on Micron MTFC4GACAJCN-1M mmc: core: disable TRIM on Kingston EMMC04G-M627 NFSD: add encoding of op_recall flag for write delegation sh: dma: Fix DMA channel offset calculation net/sched: act_pedit: Add size check for TCA_PEDIT_PARMS_EX tcp: annotate data races in __tcp_oow_rate_limited() net: bridge: keep ports without IFF_UNICAST_FLT in BR_PROMISC mode powerpc: allow PPC_EARLY_DEBUG_CPM only when SERIAL_CPM=y mailbox: ti-msgmgr: Fill non-message tx data fields with 0x0 spi: bcm-qspi: return error if neither hif_mspi nor mspi is available Add MODULE_FIRMWARE() for FIRMWARE_TG357766. sctp: fix potential deadlock on &net->sctp.addr_wq_lock rtc: st-lpc: Release some resources in st_rtc_probe() in case of error mfd: stmpe: Only disable the regulators if they are enabled mfd: intel-lpss: Add missing check for platform_get_resource mfd: rt5033: Drop rt5033-battery sub-device usb: phy: phy-tahvo: fix memory leak in tahvo_usb_probe() extcon: Fix kernel doc of property capability fields to avoid warnings extcon: Fix kernel doc of property fields to avoid warnings media: usb: siano: Fix warning due to null work_func_t function pointer media: videodev2.h: Fix struct v4l2_input tuner index comment media: usb: Check az6007_read() return value sh: j2: Use ioremap() to translate device tree address into kernel memory w1: fix loop in w1_fini() block: change all __u32 annotations to __be32 in affs_hardblocks.h USB: serial: option: add LARA-R6 01B PIDs modpost: fix off by one in is_executable_section() modpost: fix section mismatch message for R_ARM_{PC24,CALL,JUMP24} modpost: fix section mismatch message for R_ARM_ABS32 crypto: nx - fix build warnings when DEBUG_FS is not enabled pinctrl: at91-pio4: check return value of devm_kasprintf() perf dwarf-aux: Fix off-by-one in die_get_varname() pinctrl: cherryview: Return correct value if pin in push-pull mode PCI: Add pci_clear_master() stub for non-CONFIG_PCI scsi: 3w-xxxx: Add error handling for initialization failure in tw_probe() ALSA: ac97: Fix possible NULL dereference in snd_ac97_mixer drm/radeon: fix possible division-by-zero errors fbdev: omapfb: lcd_mipid: Fix an error handling path in mipid_spi_probe() soc/fsl/qe: fix usb.c build errors ASoC: es8316: Increment max value for ALC Capture Target Volume control ARM: ep93xx: fix missing-prototype warnings drm/panel: simple: fix active size for Ampire AM-480272H3TMQW-T01H Input: adxl34x - do not hardcode interrupt trigger type ARM: dts: BCM5301X: Drop "clock-names" from the SPI node Input: drv260x - sleep between polling GO bit radeon: avoid double free in ci_dpm_init() netlink: Add __sock_i_ino() for __netlink_diag_dump(). netfilter: nf_conntrack_sip: fix the ct_sip_parse_numerical_param() return value. lib/ts_bm: reset initial match offset for every block of text gtp: Fix use-after-free in __gtp_encap_destroy(). netlink: do not hard code device address lenth in fdb dumps netlink: fix potential deadlock in netlink_set_err() wifi: ath9k: convert msecs to jiffies where needed wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key() memstick r592: make memstick_debug_get_tpc_name() static kexec: fix a memory leak in crash_shrink_memory() watchdog/perf: more properly prevent false positives with turbo modes watchdog/perf: define dummy watchdog_update_hrtimer_threshold() on correct config wifi: ath9k: don't allow to overwrite ENDPOINT0 attributes wifi: ray_cs: Fix an error handling path in ray_probe() wifi: wl3501_cs: Fix an error handling path in wl3501_probe() wifi: atmel: Fix an error handling path in atmel_probe() wifi: orinoco: Fix an error handling path in orinoco_cs_probe() wifi: orinoco: Fix an error handling path in spectrum_cs_probe() wifi: ath9k: avoid referencing uninit memory in ath9k_wmi_ctrl_rx wifi: ath9k: fix AR9003 mac hardware hang check register offset calculation evm: Complete description of evm_inode_setattr() PM: domains: fix integer overflow issues in genpd_parse_state() md/raid10: fix io loss while replacement replace rdev md/raid10: fix wrong setting of max_corr_read_errors md/raid10: fix overflow of md/safe_mode_delay treewide: Remove uninitialized_var() usage drm/amdgpu: Validate VM ioctl flags. scripts/tags.sh: Resolve gtags empty index generation drm/edid: Fix uninitialized variable in drm_cvt_modes() fbdev: imsttfb: Fix use after free bug in imsttfb_probe x86/smp: Use dedicated cache-line for mwait_play_dead() x86/microcode/AMD: Load late on both threads too gfs2: Don't deref jdesc in evict Linux 4.14.321 x86: fix backwards merge of GDS/SRSO bit xen/netback: Fix buffer overrun triggered by unusual packet Documentation/x86: Fix backwards on/off logic about YMM support x86/xen: Fix secondary processors' FPU initialization KVM: Add GDS_NO support to KVM x86/speculation: Add Kconfig option for GDS x86/speculation: Add force option to GDS mitigation x86/speculation: Add Gather Data Sampling mitigation x86/fpu: Move FPU initialization into arch_cpu_finalize_init() x86/fpu: Mark init functions __init x86/fpu: Remove cpuinfo argument from init functions init, x86: Move mem_encrypt_init() into arch_cpu_finalize_init() init: Invoke arch_cpu_finalize_init() earlier init: Remove check_bugs() leftovers um/cpu: Switch to arch_cpu_finalize_init() sparc/cpu: Switch to arch_cpu_finalize_init() sh/cpu: Switch to arch_cpu_finalize_init() mips/cpu: Switch to arch_cpu_finalize_init() m68k/cpu: Switch to arch_cpu_finalize_init() ia64/cpu: Switch to arch_cpu_finalize_init() ARM: cpu: Switch to arch_cpu_finalize_init() x86/cpu: Switch to arch_cpu_finalize_init() init: Provide arch_cpu_finalize_init() Conflicts: drivers/usb/dwc3/gadget.c Change-Id: I768a646cf224b88cc616358f481218f16671094b
724 lines
17 KiB
C
724 lines
17 KiB
C
/*
|
|
* CPU subsystem support
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/cpu.h>
|
|
#include <linux/topology.h>
|
|
#include <linux/device.h>
|
|
#include <linux/node.h>
|
|
#include <linux/gfp.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/percpu.h>
|
|
#include <linux/acpi.h>
|
|
#include <linux/of.h>
|
|
#include <linux/cpufeature.h>
|
|
#include <linux/tick.h>
|
|
#include <linux/pm_qos.h>
|
|
|
|
#include "base.h"
|
|
|
|
static DEFINE_PER_CPU(struct device *, cpu_sys_devices);
|
|
|
|
static int cpu_subsys_match(struct device *dev, struct device_driver *drv)
|
|
{
|
|
/* ACPI style match is the only one that may succeed. */
|
|
if (acpi_driver_match_device(dev, drv))
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
static void change_cpu_under_node(struct cpu *cpu,
|
|
unsigned int from_nid, unsigned int to_nid)
|
|
{
|
|
int cpuid = cpu->dev.id;
|
|
unregister_cpu_under_node(cpuid, from_nid);
|
|
register_cpu_under_node(cpuid, to_nid);
|
|
cpu->node_id = to_nid;
|
|
}
|
|
|
|
static int cpu_subsys_online(struct device *dev)
|
|
{
|
|
struct cpu *cpu = container_of(dev, struct cpu, dev);
|
|
int cpuid = dev->id;
|
|
int from_nid, to_nid;
|
|
int ret;
|
|
|
|
from_nid = cpu_to_node(cpuid);
|
|
if (from_nid == NUMA_NO_NODE)
|
|
return -ENODEV;
|
|
|
|
ret = cpu_up(cpuid);
|
|
/*
|
|
* When hot adding memory to memoryless node and enabling a cpu
|
|
* on the node, node number of the cpu may internally change.
|
|
*/
|
|
to_nid = cpu_to_node(cpuid);
|
|
if (from_nid != to_nid)
|
|
change_cpu_under_node(cpu, from_nid, to_nid);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int cpu_subsys_offline(struct device *dev)
|
|
{
|
|
return cpu_down(dev->id);
|
|
}
|
|
|
|
void unregister_cpu(struct cpu *cpu)
|
|
{
|
|
int logical_cpu = cpu->dev.id;
|
|
|
|
unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu));
|
|
|
|
device_unregister(&cpu->dev);
|
|
per_cpu(cpu_sys_devices, logical_cpu) = NULL;
|
|
return;
|
|
}
|
|
|
|
#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
|
|
static ssize_t cpu_probe_store(struct device *dev,
|
|
struct device_attribute *attr,
|
|
const char *buf,
|
|
size_t count)
|
|
{
|
|
ssize_t cnt;
|
|
int ret;
|
|
|
|
ret = lock_device_hotplug_sysfs();
|
|
if (ret)
|
|
return ret;
|
|
|
|
cnt = arch_cpu_probe(buf, count);
|
|
|
|
unlock_device_hotplug();
|
|
return cnt;
|
|
}
|
|
|
|
static ssize_t cpu_release_store(struct device *dev,
|
|
struct device_attribute *attr,
|
|
const char *buf,
|
|
size_t count)
|
|
{
|
|
ssize_t cnt;
|
|
int ret;
|
|
|
|
ret = lock_device_hotplug_sysfs();
|
|
if (ret)
|
|
return ret;
|
|
|
|
cnt = arch_cpu_release(buf, count);
|
|
|
|
unlock_device_hotplug();
|
|
return cnt;
|
|
}
|
|
|
|
static DEVICE_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
|
|
static DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store);
|
|
#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
|
|
#endif /* CONFIG_HOTPLUG_CPU */
|
|
|
|
struct bus_type cpu_subsys = {
|
|
.name = "cpu",
|
|
.dev_name = "cpu",
|
|
.match = cpu_subsys_match,
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
.online = cpu_subsys_online,
|
|
.offline = cpu_subsys_offline,
|
|
#endif
|
|
};
|
|
EXPORT_SYMBOL_GPL(cpu_subsys);
|
|
|
|
#ifdef CONFIG_KEXEC
|
|
#include <linux/kexec.h>
|
|
|
|
static ssize_t show_crash_notes(struct device *dev, struct device_attribute *attr,
|
|
char *buf)
|
|
{
|
|
struct cpu *cpu = container_of(dev, struct cpu, dev);
|
|
ssize_t rc;
|
|
unsigned long long addr;
|
|
int cpunum;
|
|
|
|
cpunum = cpu->dev.id;
|
|
|
|
/*
|
|
* Might be reading other cpu's data based on which cpu read thread
|
|
* has been scheduled. But cpu data (memory) is allocated once during
|
|
* boot up and this data does not change there after. Hence this
|
|
* operation should be safe. No locking required.
|
|
*/
|
|
addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpunum));
|
|
rc = sprintf(buf, "%Lx\n", addr);
|
|
return rc;
|
|
}
|
|
static DEVICE_ATTR(crash_notes, 0400, show_crash_notes, NULL);
|
|
|
|
static ssize_t show_crash_notes_size(struct device *dev,
|
|
struct device_attribute *attr,
|
|
char *buf)
|
|
{
|
|
ssize_t rc;
|
|
|
|
rc = sprintf(buf, "%zu\n", sizeof(note_buf_t));
|
|
return rc;
|
|
}
|
|
static DEVICE_ATTR(crash_notes_size, 0400, show_crash_notes_size, NULL);
|
|
|
|
static struct attribute *crash_note_cpu_attrs[] = {
|
|
&dev_attr_crash_notes.attr,
|
|
&dev_attr_crash_notes_size.attr,
|
|
NULL
|
|
};
|
|
|
|
static struct attribute_group crash_note_cpu_attr_group = {
|
|
.attrs = crash_note_cpu_attrs,
|
|
};
|
|
#endif
|
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
|
|
static ssize_t isolate_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct cpu *cpu = container_of(dev, struct cpu, dev);
|
|
ssize_t rc;
|
|
int cpuid = cpu->dev.id;
|
|
unsigned int isolated = cpu_isolated(cpuid);
|
|
|
|
rc = snprintf(buf, PAGE_SIZE-2, "%d\n", isolated);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static DEVICE_ATTR_RO(isolate);
|
|
|
|
static struct attribute *cpu_isolated_attrs[] = {
|
|
&dev_attr_isolate.attr,
|
|
NULL
|
|
};
|
|
|
|
static struct attribute_group cpu_isolated_attr_group = {
|
|
.attrs = cpu_isolated_attrs,
|
|
};
|
|
|
|
#endif
|
|
|
|
static ssize_t show_sched_load_boost(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
ssize_t rc;
|
|
unsigned int boost;
|
|
struct cpu *cpu = container_of(dev, struct cpu, dev);
|
|
int cpuid = cpu->dev.id;
|
|
|
|
boost = per_cpu(sched_load_boost, cpuid);
|
|
rc = snprintf(buf, PAGE_SIZE-2, "%d\n", boost);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static ssize_t __ref store_sched_load_boost(struct device *dev,
|
|
struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
int err;
|
|
int boost;
|
|
struct cpu *cpu = container_of(dev, struct cpu, dev);
|
|
int cpuid = cpu->dev.id;
|
|
|
|
err = kstrtoint(strstrip((char *)buf), 0, &boost);
|
|
if (err)
|
|
return err;
|
|
|
|
/*
|
|
* -100 is low enough to cancel out CPU's load and make it near zro.
|
|
* 1000 is close to the maximum value that cpu_util_freq_{walt,pelt}
|
|
* can take without overflow.
|
|
*/
|
|
if (boost < -100 || boost > 1000)
|
|
return -EINVAL;
|
|
|
|
per_cpu(sched_load_boost, cpuid) = boost;
|
|
|
|
return count;
|
|
}
|
|
|
|
static DEVICE_ATTR(sched_load_boost, 0644,
|
|
show_sched_load_boost,
|
|
store_sched_load_boost);
|
|
|
|
static struct attribute *sched_cpu_attrs[] = {
|
|
&dev_attr_sched_load_boost.attr,
|
|
NULL
|
|
};
|
|
|
|
static struct attribute_group sched_cpu_attr_group = {
|
|
.attrs = sched_cpu_attrs,
|
|
};
|
|
|
|
static const struct attribute_group *common_cpu_attr_groups[] = {
|
|
#ifdef CONFIG_KEXEC
|
|
&crash_note_cpu_attr_group,
|
|
#endif
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
&cpu_isolated_attr_group,
|
|
#endif
|
|
&sched_cpu_attr_group,
|
|
NULL
|
|
};
|
|
|
|
static const struct attribute_group *hotplugable_cpu_attr_groups[] = {
|
|
#ifdef CONFIG_KEXEC
|
|
&crash_note_cpu_attr_group,
|
|
#endif
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
&cpu_isolated_attr_group,
|
|
#endif
|
|
&sched_cpu_attr_group,
|
|
NULL
|
|
};
|
|
|
|
/*
|
|
* Print cpu online, possible, present, and system maps
|
|
*/
|
|
|
|
struct cpu_attr {
|
|
struct device_attribute attr;
|
|
const struct cpumask *const map;
|
|
};
|
|
|
|
static ssize_t show_cpus_attr(struct device *dev,
|
|
struct device_attribute *attr,
|
|
char *buf)
|
|
{
|
|
struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr);
|
|
|
|
return cpumap_print_to_pagebuf(true, buf, ca->map);
|
|
}
|
|
|
|
#define _CPU_ATTR(name, map) \
|
|
{ __ATTR(name, 0444, show_cpus_attr, NULL), map }
|
|
|
|
/* Keep in sync with cpu_subsys_attrs */
|
|
static struct cpu_attr cpu_attrs[] = {
|
|
_CPU_ATTR(online, &__cpu_online_mask),
|
|
_CPU_ATTR(possible, &__cpu_possible_mask),
|
|
_CPU_ATTR(present, &__cpu_present_mask),
|
|
_CPU_ATTR(core_ctl_isolated, &__cpu_isolated_mask),
|
|
};
|
|
|
|
/*
|
|
* Print values for NR_CPUS and offlined cpus
|
|
*/
|
|
static ssize_t print_cpus_kernel_max(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1);
|
|
return n;
|
|
}
|
|
static DEVICE_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL);
|
|
|
|
/* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */
|
|
unsigned int total_cpus;
|
|
|
|
static ssize_t print_cpus_offline(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
int n = 0, len = PAGE_SIZE-2;
|
|
cpumask_var_t offline;
|
|
|
|
/* display offline cpus < nr_cpu_ids */
|
|
if (!alloc_cpumask_var(&offline, GFP_KERNEL))
|
|
return -ENOMEM;
|
|
cpumask_andnot(offline, cpu_possible_mask, cpu_online_mask);
|
|
n = scnprintf(buf, len, "%*pbl", cpumask_pr_args(offline));
|
|
free_cpumask_var(offline);
|
|
|
|
/* display offline cpus >= nr_cpu_ids */
|
|
if (total_cpus && nr_cpu_ids < total_cpus) {
|
|
if (n && n < len)
|
|
buf[n++] = ',';
|
|
|
|
if (nr_cpu_ids == total_cpus-1)
|
|
n += snprintf(&buf[n], len - n, "%u", nr_cpu_ids);
|
|
else
|
|
n += snprintf(&buf[n], len - n, "%u-%d",
|
|
nr_cpu_ids, total_cpus-1);
|
|
}
|
|
|
|
n += snprintf(&buf[n], len - n, "\n");
|
|
return n;
|
|
}
|
|
static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL);
|
|
|
|
static ssize_t print_cpus_isolated(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
int n = 0, len = PAGE_SIZE-2;
|
|
|
|
n = scnprintf(buf, len, "%*pbl\n", cpumask_pr_args(cpu_isolated_map));
|
|
|
|
return n;
|
|
}
|
|
static DEVICE_ATTR(isolated, 0444, print_cpus_isolated, NULL);
|
|
|
|
#ifdef CONFIG_NO_HZ_FULL
|
|
static ssize_t print_cpus_nohz_full(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
int n = 0, len = PAGE_SIZE-2;
|
|
|
|
n = scnprintf(buf, len, "%*pbl\n", cpumask_pr_args(tick_nohz_full_mask));
|
|
|
|
return n;
|
|
}
|
|
static DEVICE_ATTR(nohz_full, 0444, print_cpus_nohz_full, NULL);
|
|
#endif
|
|
|
|
static void cpu_device_release(struct device *dev)
|
|
{
|
|
/*
|
|
* This is an empty function to prevent the driver core from spitting a
|
|
* warning at us. Yes, I know this is directly opposite of what the
|
|
* documentation for the driver core and kobjects say, and the author
|
|
* of this code has already been publically ridiculed for doing
|
|
* something as foolish as this. However, at this point in time, it is
|
|
* the only way to handle the issue of statically allocated cpu
|
|
* devices. The different architectures will have their cpu device
|
|
* code reworked to properly handle this in the near future, so this
|
|
* function will then be changed to correctly free up the memory held
|
|
* by the cpu device.
|
|
*
|
|
* Never copy this way of doing things, or you too will be made fun of
|
|
* on the linux-kernel list, you have been warned.
|
|
*/
|
|
}
|
|
|
|
#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
|
|
static ssize_t print_cpu_modalias(struct device *dev,
|
|
struct device_attribute *attr,
|
|
char *buf)
|
|
{
|
|
ssize_t n;
|
|
u32 i;
|
|
|
|
n = sprintf(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:",
|
|
CPU_FEATURE_TYPEVAL);
|
|
|
|
for (i = 0; i < MAX_CPU_FEATURES; i++)
|
|
if (cpu_have_feature(i)) {
|
|
if (PAGE_SIZE < n + sizeof(",XXXX\n")) {
|
|
WARN(1, "CPU features overflow page\n");
|
|
break;
|
|
}
|
|
n += sprintf(&buf[n], ",%04X", i);
|
|
}
|
|
buf[n++] = '\n';
|
|
return n;
|
|
}
|
|
|
|
static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
|
|
{
|
|
char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
|
|
if (buf) {
|
|
print_cpu_modalias(NULL, NULL, buf);
|
|
add_uevent_var(env, "MODALIAS=%s", buf);
|
|
kfree(buf);
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* register_cpu - Setup a sysfs device for a CPU.
|
|
* @cpu - cpu->hotpluggable field set to 1 will generate a control file in
|
|
* sysfs for this CPU.
|
|
* @num - CPU number to use when creating the device.
|
|
*
|
|
* Initialize and register the CPU device.
|
|
*/
|
|
int register_cpu(struct cpu *cpu, int num)
|
|
{
|
|
int error;
|
|
|
|
cpu->node_id = cpu_to_node(num);
|
|
memset(&cpu->dev, 0x00, sizeof(struct device));
|
|
cpu->dev.id = num;
|
|
cpu->dev.bus = &cpu_subsys;
|
|
cpu->dev.release = cpu_device_release;
|
|
cpu->dev.offline_disabled = !cpu->hotpluggable;
|
|
cpu->dev.offline = !cpu_online(num);
|
|
cpu->dev.of_node = of_get_cpu_node(num, NULL);
|
|
#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
|
|
cpu->dev.bus->uevent = cpu_uevent;
|
|
#endif
|
|
cpu->dev.groups = common_cpu_attr_groups;
|
|
if (cpu->hotpluggable)
|
|
cpu->dev.groups = hotplugable_cpu_attr_groups;
|
|
error = device_register(&cpu->dev);
|
|
if (error)
|
|
return error;
|
|
|
|
per_cpu(cpu_sys_devices, num) = &cpu->dev;
|
|
register_cpu_under_node(num, cpu_to_node(num));
|
|
dev_pm_qos_expose_latency_limit(&cpu->dev, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct device *get_cpu_device(unsigned cpu)
|
|
{
|
|
if (cpu < nr_cpu_ids && cpu_possible(cpu))
|
|
return per_cpu(cpu_sys_devices, cpu);
|
|
else
|
|
return NULL;
|
|
}
|
|
EXPORT_SYMBOL_GPL(get_cpu_device);
|
|
|
|
static void device_create_release(struct device *dev)
|
|
{
|
|
kfree(dev);
|
|
}
|
|
|
|
static struct device *
|
|
__cpu_device_create(struct device *parent, void *drvdata,
|
|
const struct attribute_group **groups,
|
|
const char *fmt, va_list args)
|
|
{
|
|
struct device *dev = NULL;
|
|
int retval = -ENODEV;
|
|
|
|
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
|
if (!dev) {
|
|
retval = -ENOMEM;
|
|
goto error;
|
|
}
|
|
|
|
device_initialize(dev);
|
|
dev->parent = parent;
|
|
dev->groups = groups;
|
|
dev->release = device_create_release;
|
|
device_set_pm_not_required(dev);
|
|
dev_set_drvdata(dev, drvdata);
|
|
|
|
retval = kobject_set_name_vargs(&dev->kobj, fmt, args);
|
|
if (retval)
|
|
goto error;
|
|
|
|
retval = device_add(dev);
|
|
if (retval)
|
|
goto error;
|
|
|
|
return dev;
|
|
|
|
error:
|
|
put_device(dev);
|
|
return ERR_PTR(retval);
|
|
}
|
|
|
|
struct device *cpu_device_create(struct device *parent, void *drvdata,
|
|
const struct attribute_group **groups,
|
|
const char *fmt, ...)
|
|
{
|
|
va_list vargs;
|
|
struct device *dev;
|
|
|
|
va_start(vargs, fmt);
|
|
dev = __cpu_device_create(parent, drvdata, groups, fmt, vargs);
|
|
va_end(vargs);
|
|
return dev;
|
|
}
|
|
EXPORT_SYMBOL_GPL(cpu_device_create);
|
|
|
|
#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
|
|
static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL);
|
|
#endif
|
|
|
|
static struct attribute *cpu_root_attrs[] = {
|
|
#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
|
|
&dev_attr_probe.attr,
|
|
&dev_attr_release.attr,
|
|
#endif
|
|
&cpu_attrs[0].attr.attr,
|
|
&cpu_attrs[1].attr.attr,
|
|
&cpu_attrs[2].attr.attr,
|
|
&cpu_attrs[3].attr.attr,
|
|
&dev_attr_kernel_max.attr,
|
|
&dev_attr_offline.attr,
|
|
&dev_attr_isolated.attr,
|
|
#ifdef CONFIG_NO_HZ_FULL
|
|
&dev_attr_nohz_full.attr,
|
|
#endif
|
|
#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
|
|
&dev_attr_modalias.attr,
|
|
#endif
|
|
NULL
|
|
};
|
|
|
|
static struct attribute_group cpu_root_attr_group = {
|
|
.attrs = cpu_root_attrs,
|
|
};
|
|
|
|
static const struct attribute_group *cpu_root_attr_groups[] = {
|
|
&cpu_root_attr_group,
|
|
NULL,
|
|
};
|
|
|
|
bool cpu_is_hotpluggable(unsigned cpu)
|
|
{
|
|
struct device *dev = get_cpu_device(cpu);
|
|
return dev && container_of(dev, struct cpu, dev)->hotpluggable;
|
|
}
|
|
EXPORT_SYMBOL_GPL(cpu_is_hotpluggable);
|
|
|
|
#ifdef CONFIG_GENERIC_CPU_DEVICES
|
|
static DEFINE_PER_CPU(struct cpu, cpu_devices);
|
|
#endif
|
|
|
|
static void __init cpu_dev_register_generic(void)
|
|
{
|
|
#ifdef CONFIG_GENERIC_CPU_DEVICES
|
|
int i;
|
|
|
|
for_each_possible_cpu(i) {
|
|
if (register_cpu(&per_cpu(cpu_devices, i), i))
|
|
panic("Failed to register CPU device");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef CONFIG_GENERIC_CPU_VULNERABILITIES
|
|
|
|
ssize_t __weak cpu_show_meltdown(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return sprintf(buf, "Not affected\n");
|
|
}
|
|
|
|
ssize_t __weak cpu_show_spectre_v1(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return sprintf(buf, "Not affected\n");
|
|
}
|
|
|
|
ssize_t __weak cpu_show_spectre_v2(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return sprintf(buf, "Not affected\n");
|
|
}
|
|
|
|
ssize_t __weak cpu_show_spec_store_bypass(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return sprintf(buf, "Not affected\n");
|
|
}
|
|
|
|
ssize_t __weak cpu_show_l1tf(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return sprintf(buf, "Not affected\n");
|
|
}
|
|
|
|
ssize_t __weak cpu_show_mds(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return sprintf(buf, "Not affected\n");
|
|
}
|
|
|
|
ssize_t __weak cpu_show_tsx_async_abort(struct device *dev,
|
|
struct device_attribute *attr,
|
|
char *buf)
|
|
{
|
|
return sprintf(buf, "Not affected\n");
|
|
}
|
|
|
|
ssize_t __weak cpu_show_itlb_multihit(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return sprintf(buf, "Not affected\n");
|
|
}
|
|
|
|
ssize_t __weak cpu_show_srbds(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return sprintf(buf, "Not affected\n");
|
|
}
|
|
|
|
ssize_t __weak cpu_show_mmio_stale_data(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return sysfs_emit(buf, "Not affected\n");
|
|
}
|
|
|
|
ssize_t __weak cpu_show_retbleed(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return sysfs_emit(buf, "Not affected\n");
|
|
}
|
|
|
|
ssize_t __weak cpu_show_gds(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);
|
|
static DEVICE_ATTR(spec_store_bypass, 0444, cpu_show_spec_store_bypass, NULL);
|
|
static DEVICE_ATTR(l1tf, 0444, cpu_show_l1tf, NULL);
|
|
static DEVICE_ATTR(mds, 0444, cpu_show_mds, NULL);
|
|
static DEVICE_ATTR(tsx_async_abort, 0444, cpu_show_tsx_async_abort, NULL);
|
|
static DEVICE_ATTR(itlb_multihit, 0444, cpu_show_itlb_multihit, NULL);
|
|
static DEVICE_ATTR(srbds, 0444, cpu_show_srbds, NULL);
|
|
static DEVICE_ATTR(mmio_stale_data, 0444, cpu_show_mmio_stale_data, NULL);
|
|
static DEVICE_ATTR(retbleed, 0444, cpu_show_retbleed, NULL);
|
|
static DEVICE_ATTR(gather_data_sampling, 0444, cpu_show_gds, NULL);
|
|
|
|
static struct attribute *cpu_root_vulnerabilities_attrs[] = {
|
|
&dev_attr_meltdown.attr,
|
|
&dev_attr_spectre_v1.attr,
|
|
&dev_attr_spectre_v2.attr,
|
|
&dev_attr_spec_store_bypass.attr,
|
|
&dev_attr_l1tf.attr,
|
|
&dev_attr_mds.attr,
|
|
&dev_attr_tsx_async_abort.attr,
|
|
&dev_attr_itlb_multihit.attr,
|
|
&dev_attr_srbds.attr,
|
|
&dev_attr_mmio_stale_data.attr,
|
|
&dev_attr_retbleed.attr,
|
|
&dev_attr_gather_data_sampling.attr,
|
|
NULL
|
|
};
|
|
|
|
static const struct attribute_group cpu_root_vulnerabilities_group = {
|
|
.name = "vulnerabilities",
|
|
.attrs = cpu_root_vulnerabilities_attrs,
|
|
};
|
|
|
|
static void __init cpu_register_vulnerabilities(void)
|
|
{
|
|
if (sysfs_create_group(&cpu_subsys.dev_root->kobj,
|
|
&cpu_root_vulnerabilities_group))
|
|
pr_err("Unable to register CPU vulnerabilities\n");
|
|
}
|
|
|
|
#else
|
|
static inline void cpu_register_vulnerabilities(void) { }
|
|
#endif
|
|
|
|
void __init cpu_dev_init(void)
|
|
{
|
|
if (subsys_system_register(&cpu_subsys, cpu_root_attr_groups))
|
|
panic("Failed to register CPU subsystem");
|
|
|
|
cpu_dev_register_generic();
|
|
cpu_register_vulnerabilities();
|
|
}
|