Files
Greg Kroah-Hartman 4922049993 Merge 5.10.163 into android12-5.10-lts
Changes in 5.10.163
	usb: musb: remove extra check in musb_gadget_vbus_draw
	arm64: dts: qcom: ipq6018-cp01-c1: use BLSPI1 pins
	arm64: dts: qcom: msm8996: fix GPU OPP table
	ARM: dts: qcom: apq8064: fix coresight compatible
	arm64: dts: qcom: sdm630: fix UART1 pin bias
	arm64: dts: qcom: sdm845-cheza: fix AP suspend pin bias
	arm64: dts: qcom: msm8916: Drop MSS fallback compatible
	objtool, kcsan: Add volatile read/write instrumentation to whitelist
	ARM: dts: stm32: Drop stm32mp15xc.dtsi from Avenger96
	ARM: dts: stm32: Fix AV96 WLAN regulator gpio property
	drivers: soc: ti: knav_qmss_queue: Mark knav_acc_firmwares as static
	soc: qcom: llcc: make irq truly optional
	soc: qcom: apr: make code more reuseable
	soc: qcom: apr: Add check for idr_alloc and of_property_read_string_index
	arm: dts: spear600: Fix clcd interrupt
	soc: ti: knav_qmss_queue: Use pm_runtime_resume_and_get instead of pm_runtime_get_sync
	soc: ti: knav_qmss_queue: Fix PM disable depth imbalance in knav_queue_probe
	soc: ti: smartreflex: Fix PM disable depth imbalance in omap_sr_probe
	perf: arm_dsu: Fix hotplug callback leak in dsu_pmu_init()
	perf/smmuv3: Fix hotplug callback leak in arm_smmu_pmu_init()
	arm64: dts: ti: k3-am65-main: Drop dma-coherent in crypto node
	arm64: dts: ti: k3-j721e-main: Drop dma-coherent in crypto node
	arm64: dts: mt2712e: Fix unit_address_vs_reg warning for oscillators
	arm64: dts: mt2712e: Fix unit address for pinctrl node
	arm64: dts: mt2712-evb: Fix vproc fixed regulators unit names
	arm64: dts: mt2712-evb: Fix usb vbus regulators unit names
	arm64: dts: mediatek: pumpkin-common: Fix devicetree warnings
	arm64: dts: mediatek: mt6797: Fix 26M oscillator unit name
	ARM: dts: dove: Fix assigned-addresses for every PCIe Root Port
	ARM: dts: armada-370: Fix assigned-addresses for every PCIe Root Port
	ARM: dts: armada-xp: Fix assigned-addresses for every PCIe Root Port
	ARM: dts: armada-375: Fix assigned-addresses for every PCIe Root Port
	ARM: dts: armada-38x: Fix assigned-addresses for every PCIe Root Port
	ARM: dts: armada-39x: Fix assigned-addresses for every PCIe Root Port
	ARM: dts: turris-omnia: Add ethernet aliases
	ARM: dts: turris-omnia: Add switch port 6 node
	arm64: dts: armada-3720-turris-mox: Add missing interrupt for RTC
	pstore/ram: Fix error return code in ramoops_probe()
	ARM: mmp: fix timer_read delay
	pstore: Avoid kcore oops by vmap()ing with VM_IOREMAP
	tpm/tpm_ftpm_tee: Fix error handling in ftpm_mod_init()
	tpm/tpm_crb: Fix error message in __crb_relinquish_locality()
	sched/fair: Cleanup task_util and capacity type
	sched/uclamp: Fix relationship between uclamp and migration margin
	cpuidle: dt: Return the correct numbers of parsed idle states
	alpha: fix syscall entry in !AUDUT_SYSCALL case
	PM: hibernate: Fix mistake in kerneldoc comment
	fs: don't audit the capability check in simple_xattr_list()
	cpufreq: qcom-hw: Fix memory leak in qcom_cpufreq_hw_read_lut()
	selftests/ftrace: event_triggers: wait longer for test_event_enable
	perf: Fix possible memleak in pmu_dev_alloc()
	lib/debugobjects: fix stat count and optimize debug_objects_mem_init
	platform/x86: huawei-wmi: fix return value calculation
	timerqueue: Use rb_entry_safe() in timerqueue_getnext()
	proc: fixup uptime selftest
	lib/fonts: fix undefined behavior in bit shift for get_default_font
	ocfs2: fix memory leak in ocfs2_stack_glue_init()
	MIPS: vpe-mt: fix possible memory leak while module exiting
	MIPS: vpe-cmp: fix possible memory leak while module exiting
	selftests/efivarfs: Add checking of the test return value
	PNP: fix name memory leak in pnp_alloc_dev()
	perf/x86/intel/uncore: Fix reference count leak in hswep_has_limit_sbox()
	perf/x86/intel/uncore: Fix reference count leak in snr_uncore_mmio_map()
	perf/x86/intel/uncore: Fix reference count leak in __uncore_imc_init_box()
	platform/chrome: cros_usbpd_notify: Fix error handling in cros_usbpd_notify_init()
	irqchip: gic-pm: Use pm_runtime_resume_and_get() in gic_probe()
	EDAC/i10nm: fix refcount leak in pci_get_dev_wrapper()
	nfsd: don't call nfsd_file_put from client states seqfile display
	genirq/irqdesc: Don't try to remove non-existing sysfs files
	cpufreq: amd_freq_sensitivity: Add missing pci_dev_put()
	libfs: add DEFINE_SIMPLE_ATTRIBUTE_SIGNED for signed value
	lib/notifier-error-inject: fix error when writing -errno to debugfs file
	docs: fault-injection: fix non-working usage of negative values
	debugfs: fix error when writing negative value to atomic_t debugfs file
	ocfs2: ocfs2_mount_volume does cleanup job before return error
	ocfs2: rewrite error handling of ocfs2_fill_super
	ocfs2: fix memory leak in ocfs2_mount_volume()
	rapidio: fix possible name leaks when rio_add_device() fails
	rapidio: rio: fix possible name leak in rio_register_mport()
	clocksource/drivers/sh_cmt: Make sure channel clock supply is enabled
	clocksource/drivers/sh_cmt: Access registers according to spec
	futex: Move to kernel/futex/
	futex: Resend potentially swallowed owner death notification
	cpu/hotplug: Make target_store() a nop when target == state
	clocksource/drivers/timer-ti-dm: Fix missing clk_disable_unprepare in dmtimer_systimer_init_clock()
	ACPICA: Fix use-after-free in acpi_ut_copy_ipackage_to_ipackage()
	uprobes/x86: Allow to probe a NOP instruction with 0x66 prefix
	x86/xen: Fix memory leak in xen_smp_intr_init{_pv}()
	x86/xen: Fix memory leak in xen_init_lock_cpu()
	xen/privcmd: Fix a possible warning in privcmd_ioctl_mmap_resource()
	PM: runtime: Improve path in rpm_idle() when no callback
	PM: runtime: Do not call __rpm_callback() from rpm_idle()
	platform/x86: mxm-wmi: fix memleak in mxm_wmi_call_mx[ds|mx]()
	platform/x86: intel_scu_ipc: fix possible name leak in __intel_scu_ipc_register()
	MIPS: BCM63xx: Add check for NULL for clk in clk_enable
	MIPS: OCTEON: warn only once if deprecated link status is being used
	fs: sysv: Fix sysv_nblocks() returns wrong value
	rapidio: fix possible UAF when kfifo_alloc() fails
	eventfd: change int to __u64 in eventfd_signal() ifndef CONFIG_EVENTFD
	relay: fix type mismatch when allocating memory in relay_create_buf()
	hfs: Fix OOB Write in hfs_asc2mac
	rapidio: devices: fix missing put_device in mport_cdev_open
	wifi: ath9k: hif_usb: fix memory leak of urbs in ath9k_hif_usb_dealloc_tx_urbs()
	wifi: ath9k: hif_usb: Fix use-after-free in ath9k_hif_usb_reg_in_cb()
	wifi: rtl8xxxu: Fix reading the vendor of combo chips
	drm/bridge: adv7533: remove dynamic lane switching from adv7533 bridge
	libbpf: Fix use-after-free in btf_dump_name_dups
	libbpf: Fix null-pointer dereference in find_prog_by_sec_insn()
	pata_ipx4xx_cf: Fix unsigned comparison with less than zero
	media: coda: jpeg: Add check for kmalloc
	media: i2c: ad5820: Fix error path
	venus: pm_helpers: Fix error check in vcodec_domains_get()
	media: exynos4-is: Use v4l2_async_notifier_add_fwnode_remote_subdev
	media: exynos4-is: don't rely on the v4l2_async_subdev internals
	can: kvaser_usb: do not increase tx statistics when sending error message frames
	can: kvaser_usb: kvaser_usb_leaf: Get capabilities from device
	can: kvaser_usb: kvaser_usb_leaf: Rename {leaf,usbcan}_cmd_error_event to {leaf,usbcan}_cmd_can_error_event
	can: kvaser_usb: kvaser_usb_leaf: Handle CMD_ERROR_EVENT
	can: kvaser_usb_leaf: Set Warning state even without bus errors
	can: kvaser_usb_leaf: Fix improved state not being reported
	can: kvaser_usb_leaf: Fix wrong CAN state after stopping
	can: kvaser_usb_leaf: Fix bogus restart events
	can: kvaser_usb: Add struct kvaser_usb_busparams
	can: kvaser_usb: Compare requested bittiming parameters with actual parameters in do_set_{,data}_bittiming
	drm/rockchip: lvds: fix PM usage counter unbalance in poweron
	clk: renesas: r9a06g032: Repair grave increment error
	spi: Update reference to struct spi_controller
	drm/panel/panel-sitronix-st7701: Remove panel on DSI attach failure
	ima: Fix fall-through warnings for Clang
	ima: Handle -ESTALE returned by ima_filter_rule_match()
	drm/msm/hdmi: switch to drm_bridge_connector
	drm/msm/hdmi: drop unused GPIO support
	bpf: Fix slot type check in check_stack_write_var_off
	media: vivid: fix compose size exceed boundary
	media: platform: exynos4-is: fix return value check in fimc_md_probe()
	bpf: propagate precision in ALU/ALU64 operations
	bpf: Check the other end of slot_type for STACK_SPILL
	bpf: propagate precision across all frames, not just the last one
	clk: qcom: gcc-sm8250: Use retention mode for USB GDSCs
	mtd: Fix device name leak when register device failed in add_mtd_device()
	Input: joystick - fix Kconfig warning for JOYSTICK_ADC
	wifi: rsi: Fix handling of 802.3 EAPOL frames sent via control port
	media: camss: Clean up received buffers on failed start of streaming
	net, proc: Provide PROC_FS=n fallback for proc_create_net_single_write()
	rxrpc: Fix ack.bufferSize to be 0 when generating an ack
	drm/radeon: Add the missed acpi_put_table() to fix memory leak
	drm/mediatek: Modify dpi power on/off sequence.
	ASoC: pxa: fix null-pointer dereference in filter()
	regulator: core: fix unbalanced of node refcount in regulator_dev_lookup()
	amdgpu/pm: prevent array underflow in vega20_odn_edit_dpm_table()
	drm/fourcc: Add packed 10bit YUV 4:2:0 format
	drm/fourcc: Fix vsub/hsub for Q410 and Q401
	integrity: Fix memory leakage in keyring allocation error path
	ima: Fix misuse of dereference of pointer in template_desc_init_fields()
	wifi: ath10k: Fix return value in ath10k_pci_init()
	mtd: lpddr2_nvm: Fix possible null-ptr-deref
	Input: elants_i2c - properly handle the reset GPIO when power is off
	media: vidtv: Fix use-after-free in vidtv_bridge_dvb_init()
	media: solo6x10: fix possible memory leak in solo_sysfs_init()
	media: platform: exynos4-is: Fix error handling in fimc_md_init()
	media: videobuf-dma-contig: use dma_mmap_coherent
	inet: add READ_ONCE(sk->sk_bound_dev_if) in inet_csk_bind_conflict()
	bpf: Move skb->len == 0 checks into __bpf_redirect
	HID: hid-sensor-custom: set fixed size for custom attributes
	ALSA: pcm: fix undefined behavior in bit shift for SNDRV_PCM_RATE_KNOT
	ALSA: seq: fix undefined behavior in bit shift for SNDRV_SEQ_FILTER_USE_EVENT
	regulator: core: use kfree_const() to free space conditionally
	clk: rockchip: Fix memory leak in rockchip_clk_register_pll()
	drm/amdgpu: fix pci device refcount leak
	bonding: fix link recovery in mode 2 when updelay is nonzero
	mtd: maps: pxa2xx-flash: fix memory leak in probe
	drbd: fix an invalid memory access caused by incorrect use of list iterator
	ASoC: qcom: Add checks for devm_kcalloc
	media: vimc: Fix wrong function called when vimc_init() fails
	media: imon: fix a race condition in send_packet()
	clk: imx: replace osc_hdmi with dummy
	pinctrl: pinconf-generic: add missing of_node_put()
	media: dvb-core: Fix ignored return value in dvb_register_frontend()
	media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()
	media: s5p-mfc: Add variant data for MFC v7 hardware for Exynos 3250 SoC
	drm/tegra: Add missing clk_disable_unprepare() in tegra_dc_probe()
	ASoC: dt-bindings: wcd9335: fix reset line polarity in example
	ASoC: mediatek: mtk-btcvsd: Add checks for write and read of mtk_btcvsd_snd
	NFSv4.2: Clear FATTR4_WORD2_SECURITY_LABEL when done decoding
	NFSv4.2: Fix a memory stomp in decode_attr_security_label
	NFSv4.2: Fix initialisation of struct nfs4_label
	NFSv4: Fix a deadlock between nfs4_open_recover_helper() and delegreturn
	NFS: Fix an Oops in nfs_d_automount()
	ALSA: asihpi: fix missing pci_disable_device()
	wifi: iwlwifi: mvm: fix double free on tx path.
	ASoC: mediatek: mt8173: Fix debugfs registration for components
	ASoC: mediatek: mt8173: Enable IRQ when pdata is ready
	drm/amd/pm/smu11: BACO is supported when it's in BACO state
	drm/radeon: Fix PCI device refcount leak in radeon_atrm_get_bios()
	drm/amdgpu: Fix PCI device refcount leak in amdgpu_atrm_get_bios()
	ASoC: pcm512x: Fix PM disable depth imbalance in pcm512x_probe
	netfilter: conntrack: set icmpv6 redirects as RELATED
	bpf, sockmap: Fix repeated calls to sock_put() when msg has more_data
	bpf, sockmap: Fix data loss caused by using apply_bytes on ingress redirect
	bonding: uninitialized variable in bond_miimon_inspect()
	spi: spidev: mask SPI_CS_HIGH in SPI_IOC_RD_MODE
	wifi: mac80211: fix memory leak in ieee80211_if_add()
	wifi: cfg80211: Fix not unregister reg_pdev when load_builtin_regdb_keys() fails
	wifi: mt76: fix coverity overrun-call in mt76_get_txpower()
	regulator: core: fix module refcount leak in set_supply()
	clk: qcom: clk-krait: fix wrong div2 functions
	hsr: Add a rcu-read lock to hsr_forward_skb().
	net: hsr: generate supervision frame without HSR/PRP tag
	hsr: Disable netpoll.
	hsr: Synchronize sending frames to have always incremented outgoing seq nr.
	hsr: Synchronize sequence number updates.
	configfs: fix possible memory leak in configfs_create_dir()
	regulator: core: fix resource leak in regulator_register()
	hwmon: (jc42) Convert register access and caching to regmap/regcache
	hwmon: (jc42) Restore the min/max/critical temperatures on resume
	bpf, sockmap: fix race in sock_map_free()
	ALSA: pcm: Set missing stop_operating flag at undoing trigger start
	media: saa7164: fix missing pci_disable_device()
	ALSA: mts64: fix possible null-ptr-defer in snd_mts64_interrupt
	xprtrdma: Fix regbuf data not freed in rpcrdma_req_create()
	SUNRPC: Fix missing release socket in rpc_sockname()
	NFSv4.x: Fail client initialisation if state manager thread can't run
	mmc: alcor: fix return value check of mmc_add_host()
	mmc: moxart: fix return value check of mmc_add_host()
	mmc: mxcmmc: fix return value check of mmc_add_host()
	mmc: pxamci: fix return value check of mmc_add_host()
	mmc: rtsx_usb_sdmmc: fix return value check of mmc_add_host()
	mmc: toshsd: fix return value check of mmc_add_host()
	mmc: vub300: fix return value check of mmc_add_host()
	mmc: wmt-sdmmc: fix return value check of mmc_add_host()
	mmc: atmel-mci: fix return value check of mmc_add_host()
	mmc: omap_hsmmc: fix return value check of mmc_add_host()
	mmc: meson-gx: fix return value check of mmc_add_host()
	mmc: via-sdmmc: fix return value check of mmc_add_host()
	mmc: wbsd: fix return value check of mmc_add_host()
	mmc: mmci: fix return value check of mmc_add_host()
	media: c8sectpfe: Add of_node_put() when breaking out of loop
	media: coda: Add check for dcoda_iram_alloc
	media: coda: Add check for kmalloc
	clk: samsung: Fix memory leak in _samsung_clk_register_pll()
	spi: spi-gpio: Don't set MOSI as an input if not 3WIRE mode
	wifi: rtl8xxxu: Add __packed to struct rtl8723bu_c2h
	wifi: rtl8xxxu: Fix the channel width reporting
	wifi: brcmfmac: Fix error return code in brcmf_sdio_download_firmware()
	blktrace: Fix output non-blktrace event when blk_classic option enabled
	clk: socfpga: clk-pll: Remove unused variable 'rc'
	clk: socfpga: use clk_hw_register for a5/c5
	clk: socfpga: Fix memory leak in socfpga_gate_init()
	net: vmw_vsock: vmci: Check memcpy_from_msg()
	net: defxx: Fix missing err handling in dfx_init()
	net: stmmac: selftests: fix potential memleak in stmmac_test_arpoffload()
	drivers: net: qlcnic: Fix potential memory leak in qlcnic_sriov_init()
	of: overlay: fix null pointer dereferencing in find_dup_cset_node_entry() and find_dup_cset_prop()
	ethernet: s2io: don't call dev_kfree_skb() under spin_lock_irqsave()
	net: farsync: Fix kmemleak when rmmods farsync
	net/tunnel: wait until all sk_user_data reader finish before releasing the sock
	net: apple: mace: don't call dev_kfree_skb() under spin_lock_irqsave()
	net: apple: bmac: don't call dev_kfree_skb() under spin_lock_irqsave()
	net: emaclite: don't call dev_kfree_skb() under spin_lock_irqsave()
	net: ethernet: dnet: don't call dev_kfree_skb() under spin_lock_irqsave()
	hamradio: don't call dev_kfree_skb() under spin_lock_irqsave()
	net: amd: lance: don't call dev_kfree_skb() under spin_lock_irqsave()
	net: amd-xgbe: Fix logic around active and passive cables
	net: amd-xgbe: Check only the minimum speed for active/passive cables
	can: tcan4x5x: Remove invalid write in clear_interrupts
	net: lan9303: Fix read error execution path
	ntb_netdev: Use dev_kfree_skb_any() in interrupt context
	sctp: sysctl: make extra pointers netns aware
	Bluetooth: btusb: don't call kfree_skb() under spin_lock_irqsave()
	Bluetooth: hci_qca: don't call kfree_skb() under spin_lock_irqsave()
	Bluetooth: hci_ll: don't call kfree_skb() under spin_lock_irqsave()
	Bluetooth: hci_h5: don't call kfree_skb() under spin_lock_irqsave()
	Bluetooth: hci_bcsp: don't call kfree_skb() under spin_lock_irqsave()
	Bluetooth: hci_core: don't call kfree_skb() under spin_lock_irqsave()
	Bluetooth: RFCOMM: don't call kfree_skb() under spin_lock_irqsave()
	stmmac: fix potential division by 0
	apparmor: fix a memleak in multi_transaction_new()
	apparmor: fix lockdep warning when removing a namespace
	apparmor: Fix abi check to include v8 abi
	crypto: sun8i-ss - use dma_addr instead u32
	crypto: nitrox - avoid double free on error path in nitrox_sriov_init()
	scsi: core: Fix a race between scsi_done() and scsi_timeout()
	apparmor: Use pointer to struct aa_label for lbs_cred
	PCI: dwc: Fix n_fts[] array overrun
	RDMA/core: Fix order of nldev_exit call
	PCI: pci-epf-test: Register notifier if only core_init_notifier is enabled
	f2fs: Fix the race condition of resize flag between resizefs
	crypto: rockchip - do not do custom power management
	crypto: rockchip - do not store mode globally
	crypto: rockchip - add fallback for cipher
	crypto: rockchip - add fallback for ahash
	crypto: rockchip - better handle cipher key
	crypto: rockchip - remove non-aligned handling
	crypto: rockchip - delete unneeded variable initialization
	crypto: rockchip - rework by using crypto_engine
	apparmor: Fix memleak in alloc_ns()
	f2fs: fix normal discard process
	RDMA/siw: Fix immediate work request flush to completion queue
	RDMA/nldev: Return "-EAGAIN" if the cm_id isn't from expected port
	RDMA/siw: Set defined status for work completion with undefined status
	scsi: scsi_debug: Fix a warning in resp_write_scat()
	crypto: ccree - Remove debugfs when platform_driver_register failed
	crypto: cryptd - Use request context instead of stack for sub-request
	crypto: hisilicon/qm - add missing pci_dev_put() in q_num_set()
	RDMA/hns: Repacing 'dseg_len' by macros in fill_ext_sge_inl_data()
	RDMA/hns: Fix ext_sge num error when post send
	PCI: Check for alloc failure in pci_request_irq()
	RDMA/hfi: Decrease PCI device reference count in error path
	crypto: ccree - Make cc_debugfs_global_fini() available for module init function
	RDMA/hns: fix memory leak in hns_roce_alloc_mr()
	RDMA/rxe: Fix NULL-ptr-deref in rxe_qp_do_cleanup() when socket create failed
	scsi: hpsa: Fix possible memory leak in hpsa_init_one()
	crypto: tcrypt - Fix multibuffer skcipher speed test mem leak
	padata: Always leave BHs disabled when running ->parallel()
	padata: Fix list iterator in padata_do_serial()
	scsi: mpt3sas: Fix possible resource leaks in mpt3sas_transport_port_add()
	scsi: hpsa: Fix error handling in hpsa_add_sas_host()
	scsi: hpsa: Fix possible memory leak in hpsa_add_sas_device()
	scsi: scsi_debug: Fix a warning in resp_verify()
	scsi: scsi_debug: Fix a warning in resp_report_zones()
	scsi: fcoe: Fix possible name leak when device_register() fails
	scsi: scsi_debug: Fix possible name leak in sdebug_add_host_helper()
	scsi: ipr: Fix WARNING in ipr_init()
	scsi: fcoe: Fix transport not deattached when fcoe_if_init() fails
	scsi: snic: Fix possible UAF in snic_tgt_create()
	RDMA/nldev: Add checks for nla_nest_start() in fill_stat_counter_qps()
	f2fs: avoid victim selection from previous victim section
	RDMA/nldev: Fix failure to send large messages
	crypto: amlogic - Remove kcalloc without check
	crypto: omap-sham - Use pm_runtime_resume_and_get() in omap_sham_probe()
	riscv/mm: add arch hook arch_clear_hugepage_flags
	RDMA/hfi1: Fix error return code in parse_platform_config()
	RDMA/srp: Fix error return code in srp_parse_options()
	orangefs: Fix sysfs not cleanup when dev init failed
	RDMA/hns: Fix PBL page MTR find
	RDMA/hns: Fix page size cap from firmware
	crypto: img-hash - Fix variable dereferenced before check 'hdev->req'
	hwrng: amd - Fix PCI device refcount leak
	hwrng: geode - Fix PCI device refcount leak
	IB/IPoIB: Fix queue count inconsistency for PKEY child interfaces
	drivers: dio: fix possible memory leak in dio_init()
	serial: tegra: Read DMA status before terminating
	class: fix possible memory leak in __class_register()
	vfio: platform: Do not pass return buffer to ACPI _RST method
	uio: uio_dmem_genirq: Fix missing unlock in irq configuration
	uio: uio_dmem_genirq: Fix deadlock between irq config and handling
	usb: fotg210-udc: Fix ages old endianness issues
	staging: vme_user: Fix possible UAF in tsi148_dma_list_add
	usb: typec: Check for ops->exit instead of ops->enter in altmode_exit
	usb: typec: tcpci: fix of node refcount leak in tcpci_register_port()
	usb: typec: tipd: Fix spurious fwnode_handle_put in error path
	serial: amba-pl011: avoid SBSA UART accessing DMACR register
	serial: pl011: Do not clear RX FIFO & RX interrupt in unthrottle.
	serial: pch: Fix PCI device refcount leak in pch_request_dma()
	tty: serial: clean up stop-tx part in altera_uart_tx_chars()
	tty: serial: altera_uart_{r,t}x_chars() need only uart_port
	serial: altera_uart: fix locking in polling mode
	serial: sunsab: Fix error handling in sunsab_init()
	test_firmware: fix memory leak in test_firmware_init()
	misc: ocxl: fix possible name leak in ocxl_file_register_afu()
	ocxl: fix pci device refcount leak when calling get_function_0()
	misc: tifm: fix possible memory leak in tifm_7xx1_switch_media()
	misc: sgi-gru: fix use-after-free error in gru_set_context_option, gru_fault and gru_handle_user_call_os
	firmware: raspberrypi: fix possible memory leak in rpi_firmware_probe()
	cxl: fix possible null-ptr-deref in cxl_guest_init_afu|adapter()
	cxl: fix possible null-ptr-deref in cxl_pci_init_afu|adapter()
	iio: temperature: ltc2983: make bulk write buffer DMA-safe
	genirq: Add IRQF_NO_AUTOEN for request_irq/nmi()
	iio:imu:adis: Use IRQF_NO_AUTOEN instead of irq request then disable
	iio: adis: handle devices that cannot unmask the drdy pin
	iio: adis: stylistic changes
	iio:imu:adis: Move exports into IIO_ADISLIB namespace
	iio: adis: add '__adis_enable_irq()' implementation
	counter: stm32-lptimer-cnt: fix the check on arr and cmp registers update
	usb: roles: fix of node refcount leak in usb_role_switch_is_parent()
	usb: gadget: f_hid: optional SETUP/SET_REPORT mode
	usb: gadget: f_hid: fix f_hidg lifetime vs cdev
	usb: gadget: f_hid: fix refcount leak on error path
	drivers: mcb: fix resource leak in mcb_probe()
	mcb: mcb-parse: fix error handing in chameleon_parse_gdd()
	chardev: fix error handling in cdev_device_add()
	i2c: pxa-pci: fix missing pci_disable_device() on error in ce4100_i2c_probe
	staging: rtl8192u: Fix use after free in ieee80211_rx()
	staging: rtl8192e: Fix potential use-after-free in rtllib_rx_Monitor()
	vme: Fix error not catched in fake_init()
	gpiolib: Get rid of redundant 'else'
	gpiolib: cdev: fix NULL-pointer dereferences
	i2c: mux: reg: check return value after calling platform_get_resource()
	i2c: ismt: Fix an out-of-bounds bug in ismt_access()
	usb: storage: Add check for kcalloc
	tracing/hist: Fix issue of losting command info in error_log
	samples: vfio-mdev: Fix missing pci_disable_device() in mdpy_fb_probe()
	thermal/drivers/imx8mm_thermal: Validate temperature range
	fbdev: ssd1307fb: Drop optional dependency
	fbdev: pm2fb: fix missing pci_disable_device()
	fbdev: via: Fix error in via_core_init()
	fbdev: vermilion: decrease reference count in error path
	fbdev: uvesafb: Fixes an error handling path in uvesafb_probe()
	HSI: omap_ssi_core: fix unbalanced pm_runtime_disable()
	HSI: omap_ssi_core: fix possible memory leak in ssi_probe()
	power: supply: fix residue sysfs file in error handle route of __power_supply_register()
	perf trace: Return error if a system call doesn't exist
	perf trace: Use macro RAW_SYSCALL_ARGS_NUM to replace number
	perf trace: Handle failure when trace point folder is missed
	perf symbol: correction while adjusting symbol
	HSI: omap_ssi_core: Fix error handling in ssi_init()
	power: supply: fix null pointer dereferencing in power_supply_get_battery_info
	RDMA/siw: Fix pointer cast warning
	iommu/sun50i: Fix reset release
	iommu/sun50i: Consider all fault sources for reset
	iommu/sun50i: Fix R/W permission check
	iommu/sun50i: Fix flush size
	phy: usb: s2 WoL wakeup_count not incremented for USB->Eth devices
	include/uapi/linux/swab: Fix potentially missing __always_inline
	pwm: tegra: Improve required rate calculation
	dmaengine: idxd: Fix crc_val field for completion record
	rtc: rtc-cmos: Do not check ACPI_FADT_LOW_POWER_S0
	rtc: cmos: Fix event handler registration ordering issue
	rtc: cmos: Fix wake alarm breakage
	rtc: cmos: fix build on non-ACPI platforms
	rtc: cmos: Call cmos_wake_setup() from cmos_do_probe()
	rtc: cmos: Call rtc_wake_setup() from cmos_do_probe()
	rtc: cmos: Eliminate forward declarations of some functions
	rtc: cmos: Rename ACPI-related functions
	rtc: cmos: Disable ACPI RTC event on removal
	rtc: snvs: Allow a time difference on clock register read
	rtc: pcf85063: Fix reading alarm
	iommu/amd: Fix pci device refcount leak in ppr_notifier()
	iommu/fsl_pamu: Fix resource leak in fsl_pamu_probe()
	macintosh: fix possible memory leak in macio_add_one_device()
	macintosh/macio-adb: check the return value of ioremap()
	powerpc/52xx: Fix a resource leak in an error handling path
	cxl: Fix refcount leak in cxl_calc_capp_routing
	powerpc/xmon: Enable breakpoints on 8xx
	powerpc/xmon: Fix -Wswitch-unreachable warning in bpt_cmds
	powerpc/xive: add missing iounmap() in error path in xive_spapr_populate_irq_data()
	kbuild: remove unneeded mkdir for external modules_install
	kbuild: unify modules(_install) for in-tree and external modules
	kbuild: refactor single builds of *.ko
	powerpc/perf: callchain validate kernel stack pointer bounds
	powerpc/83xx/mpc832x_rdb: call platform_device_put() in error case in of_fsl_spi_probe()
	powerpc/hv-gpci: Fix hv_gpci event list
	selftests/powerpc: Fix resource leaks
	iommu/sun50i: Remove IOMMU_DOMAIN_IDENTITY
	pwm: sifive: Call pwm_sifive_update_clock() while mutex is held
	remoteproc: sysmon: fix memory leak in qcom_add_sysmon_subdev()
	remoteproc: qcom_q6v5_pas: disable wakeup on probe fail or remove
	remoteproc: qcom_q6v5_pas: detach power domains on remove
	remoteproc: qcom_q6v5_pas: Fix missing of_node_put() in adsp_alloc_memory_region()
	powerpc/eeh: Drop redundant spinlock initialization
	powerpc/pseries/eeh: use correct API for error log size
	netfilter: flowtable: really fix NAT IPv6 offload
	rtc: st-lpc: Add missing clk_disable_unprepare in st_rtc_probe()
	rtc: pic32: Move devm_rtc_allocate_device earlier in pic32_rtc_probe()
	rtc: pcf85063: fix pcf85063_clkout_control
	NFSD: Remove spurious cb_setup_err tracepoint
	nfsd: under NFSv4.1, fix double svc_xprt_put on rpc_create failure
	net: macsec: fix net device access prior to holding a lock
	mISDN: hfcsusb: don't call dev_kfree_skb/kfree_skb() under spin_lock_irqsave()
	mISDN: hfcpci: don't call dev_kfree_skb/kfree_skb() under spin_lock_irqsave()
	mISDN: hfcmulti: don't call dev_kfree_skb/kfree_skb() under spin_lock_irqsave()
	nfc: pn533: Clear nfc_target before being used
	r6040: Fix kmemleak in probe and remove
	net: switch to storing KCOV handle directly in sk_buff
	net: add inline function skb_csum_is_sctp
	net: igc: use skb_csum_is_sctp instead of protocol check
	net: add a helper to avoid issues with HW TX timestamping and SO_TXTIME
	igc: Enhance Qbv scheduling by using first flag bit
	igc: Use strict cycles for Qbv scheduling
	igc: Add checking for basetime less than zero
	igc: recalculate Qbv end_time by considering cycle time
	igc: Lift TAPRIO schedule restriction
	igc: Set Qbv start_time and end_time to end_time if not being configured in GCL
	rtc: mxc_v2: Add missing clk_disable_unprepare()
	selftests: devlink: fix the fd redirect in dummy_reporter_test
	openvswitch: Fix flow lookup to use unmasked key
	skbuff: Account for tail adjustment during pull operations
	mailbox: zynq-ipi: fix error handling while device_register() fails
	net_sched: reject TCF_EM_SIMPLE case for complex ematch module
	rxrpc: Fix missing unlock in rxrpc_do_sendmsg()
	myri10ge: Fix an error handling path in myri10ge_probe()
	net: stream: purge sk_error_queue in sk_stream_kill_queues()
	rcu: Fix __this_cpu_read() lockdep warning in rcu_force_quiescent_state()
	arm64: make is_ttbrX_addr() noinstr-safe
	video: hyperv_fb: Avoid taking busy spinlock on panic path
	x86/hyperv: Remove unregister syscore call from Hyper-V cleanup
	binfmt_misc: fix shift-out-of-bounds in check_special_flags
	fs: jfs: fix shift-out-of-bounds in dbAllocAG
	udf: Avoid double brelse() in udf_rename()
	fs: jfs: fix shift-out-of-bounds in dbDiscardAG
	ACPICA: Fix error code path in acpi_ds_call_control_method()
	nilfs2: fix shift-out-of-bounds/overflow in nilfs_sb2_bad_offset()
	nilfs2: fix shift-out-of-bounds due to too large exponent of block size
	acct: fix potential integer overflow in encode_comp_t()
	hfs: fix OOB Read in __hfs_brec_find
	drm/etnaviv: add missing quirks for GC300
	brcmfmac: return error when getting invalid max_flowrings from dongle
	wifi: ath9k: verify the expected usb_endpoints are present
	wifi: ar5523: Fix use-after-free on ar5523_cmd() timed out
	ASoC: codecs: rt298: Add quirk for KBL-R RVP platform
	ipmi: fix memleak when unload ipmi driver
	drm/amd/display: prevent memory leak
	qed (gcc13): use u16 for fid to be big enough
	bpf: make sure skb->len != 0 when redirecting to a tunneling device
	net: ethernet: ti: Fix return type of netcp_ndo_start_xmit()
	hamradio: baycom_epp: Fix return type of baycom_send_packet()
	wifi: brcmfmac: Fix potential shift-out-of-bounds in brcmf_fw_alloc_request()
	igb: Do not free q_vector unless new one was allocated
	drm/amdgpu: Fix type of second parameter in trans_msg() callback
	drm/amdgpu: Fix type of second parameter in odn_edit_dpm_table() callback
	s390/ctcm: Fix return type of ctc{mp,}m_tx()
	s390/netiucv: Fix return type of netiucv_tx()
	s390/lcs: Fix return type of lcs_start_xmit()
	drm/msm: Use drm_mode_copy()
	drm/rockchip: Use drm_mode_copy()
	drm/sti: Use drm_mode_copy()
	drivers/md/md-bitmap: check the return value of md_bitmap_get_counter()
	md/raid1: stop mdx_raid1 thread when raid1 array run failed
	drm/amd/display: fix array index out of bound error in bios parser
	net: add atomic_long_t to net_device_stats fields
	mrp: introduce active flags to prevent UAF when applicant uninit
	ppp: associate skb with a device at tx
	bpf: Prevent decl_tag from being referenced in func_proto arg
	ethtool: avoiding integer overflow in ethtool_phys_id()
	media: dvb-frontends: fix leak of memory fw
	media: dvbdev: adopts refcnt to avoid UAF
	media: dvb-usb: fix memory leak in dvb_usb_adapter_init()
	blk-mq: fix possible memleak when register 'hctx' failed
	libbpf: Avoid enum forward-declarations in public API in C++ mode
	regulator: core: fix use_count leakage when handling boot-on
	mmc: f-sdh30: Add quirks for broken timeout clock capability
	mmc: renesas_sdhi: better reset from HS400 mode
	media: si470x: Fix use-after-free in si470x_int_in_callback()
	clk: st: Fix memory leak in st_of_quadfs_setup()
	hugetlbfs: fix null-ptr-deref in hugetlbfs_parse_param()
	drm/fsl-dcu: Fix return type of fsl_dcu_drm_connector_mode_valid()
	drm/sti: Fix return type of sti_{dvo,hda,hdmi}_connector_mode_valid()
	orangefs: Fix kmemleak in orangefs_prepare_debugfs_help_string()
	orangefs: Fix kmemleak in orangefs_{kernel,client}_debug_init()
	hwmon: (jc42) Fix missing unlock on error in jc42_write()
	ALSA/ASoC: hda: move/rename snd_hdac_ext_stop_streams to hdac_stream.c
	ALSA: hda: add snd_hdac_stop_streams() helper
	ASoC: Intel: Skylake: Fix driver hang during shutdown
	ASoC: mediatek: mt8173-rt5650-rt5514: fix refcount leak in mt8173_rt5650_rt5514_dev_probe()
	ASoC: audio-graph-card: fix refcount leak of cpu_ep in __graph_for_each_link()
	ASoC: rockchip: pdm: Add missing clk_disable_unprepare() in rockchip_pdm_runtime_resume()
	ASoC: wm8994: Fix potential deadlock
	ASoC: rockchip: spdif: Add missing clk_disable_unprepare() in rk_spdif_runtime_resume()
	ASoC: rt5670: Remove unbalanced pm_runtime_put()
	LoadPin: Ignore the "contents" argument of the LSM hooks
	pstore: Switch pmsg_lock to an rt_mutex to avoid priority inversion
	perf debug: Set debug_peo_args and redirect_to_stderr variable to correct values in perf_quiet_option()
	afs: Fix lost servers_outstanding count
	pstore: Make sure CONFIG_PSTORE_PMSG selects CONFIG_RT_MUTEXES
	ima: Simplify ima_lsm_copy_rule
	ALSA: usb-audio: add the quirk for KT0206 device
	ALSA: hda/realtek: Add quirk for Lenovo TianYi510Pro-14IOB
	ALSA: hda/hdmi: Add HP Device 0x8711 to force connect list
	usb: dwc3: Fix race between dwc3_set_mode and __dwc3_set_mode
	usb: dwc3: core: defer probe on ulpi_read_id timeout
	HID: wacom: Ensure bootloader PID is usable in hidraw mode
	HID: mcp2221: don't connect hidraw
	reiserfs: Add missing calls to reiserfs_security_free()
	iio: adc: ad_sigma_delta: do not use internal iio_dev lock
	iio: adc128s052: add proper .data members in adc128_of_match table
	regulator: core: fix deadlock on regulator enable
	gcov: add support for checksum field
	ovl: fix use inode directly in rcu-walk mode
	media: dvbdev: fix build warning due to comments
	media: dvbdev: fix refcnt bug
	pwm: tegra: Fix 32 bit build
	usb: dwc3: qcom: Fix memory leak in dwc3_qcom_interconnect_init
	cifs: fix oops during encryption
	nvme-pci: fix doorbell buffer value endianness
	nvme-pci: fix mempool alloc size
	nvme-pci: fix page size checks
	ata: ahci: Fix PCS quirk application for suspend
	nvme: fix the NVME_CMD_EFFECTS_CSE_MASK definition
	nvmet: don't defer passthrough commands with trivial effects to the workqueue
	objtool: Fix SEGFAULT
	powerpc/rtas: avoid device tree lookups in rtas_os_term()
	powerpc/rtas: avoid scheduling in rtas_os_term()
	HID: multitouch: fix Asus ExpertBook P2 P2451FA trackpoint
	HID: plantronics: Additional PIDs for double volume key presses quirk
	pstore/zone: Use GFP_ATOMIC to allocate zone buffer
	hfsplus: fix bug causing custom uid and gid being unable to be assigned with mount
	binfmt: Fix error return code in load_elf_fdpic_binary()
	ovl: Use ovl mounter's fsuid and fsgid in ovl_link()
	ALSA: line6: correct midi status byte when receiving data from podxt
	ALSA: line6: fix stack overflow in line6_midi_transmit
	pnode: terminate at peers of source
	md: fix a crash in mempool_free
	mm, compaction: fix fast_isolate_around() to stay within boundaries
	f2fs: should put a page when checking the summary info
	mmc: vub300: fix warning - do not call blocking ops when !TASK_RUNNING
	tpm: acpi: Call acpi_put_table() to fix memory leak
	tpm: tpm_crb: Add the missed acpi_put_table() to fix memory leak
	tpm: tpm_tis: Add the missed acpi_put_table() to fix memory leak
	SUNRPC: Don't leak netobj memory when gss_read_proxy_verf() fails
	kcsan: Instrument memcpy/memset/memmove with newer Clang
	ASoC: Intel/SOF: use set_stream() instead of set_tdm_slots() for HDAudio
	ASoC/SoundWire: dai: expand 'stream' concept beyond SoundWire
	net/mlx5e: Fix nullptr in mlx5e_tc_add_fdb_flow()
	wifi: rtlwifi: remove always-true condition pointed out by GCC 12
	wifi: rtlwifi: 8192de: correct checking of IQK reload
	torture: Exclude "NOHZ tick-stop error" from fatal errors
	rcu: Prevent lockdep-RCU splats on lock acquisition/release
	net/af_packet: add VLAN support for AF_PACKET SOCK_RAW GSO
	net/af_packet: make sure to pull mac header
	media: stv0288: use explicitly signed char
	soc: qcom: Select REMAP_MMIO for LLCC driver
	kest.pl: Fix grub2 menu handling for rebooting
	ktest.pl minconfig: Unset configs instead of just removing them
	jbd2: use the correct print format
	arm64: dts: qcom: sdm845-db845c: correct SPI2 pins drive strength
	mmc: sdhci-sprd: Disable CLK_AUTO when the clock is less than 400K
	btrfs: fix resolving backrefs for inline extent followed by prealloc
	ARM: ux500: do not directly dereference __iomem
	arm64: dts: qcom: sdm850-lenovo-yoga-c630: correct I2C12 pins drive strength
	selftests: Use optional USERCFLAGS and USERLDFLAGS
	PM/devfreq: governor: Add a private governor_data for governor
	cpufreq: Init completion before kobject_init_and_add()
	ALSA: patch_realtek: Fix Dell Inspiron Plus 16
	ALSA: hda/realtek: Apply dual codec fixup for Dell Latitude laptops
	dm cache: Fix ABBA deadlock between shrink_slab and dm_cache_metadata_abort
	dm thin: Fix ABBA deadlock between shrink_slab and dm_pool_abort_metadata
	dm thin: Use last transaction's pmd->root when commit failed
	dm thin: resume even if in FAIL mode
	dm thin: Fix UAF in run_timer_softirq()
	dm integrity: Fix UAF in dm_integrity_dtr()
	dm clone: Fix UAF in clone_dtr()
	dm cache: Fix UAF in destroy()
	dm cache: set needs_check flag after aborting metadata
	tracing/hist: Fix out-of-bound write on 'action_data.var_ref_idx'
	perf/core: Call LSM hook after copying perf_event_attr
	KVM: nVMX: Inject #GP, not #UD, if "generic" VMXON CR0/CR4 check fails
	x86/microcode/intel: Do not retry microcode reloading on the APs
	ftrace/x86: Add back ftrace_expected for ftrace bug reports
	x86/kprobes: Fix kprobes instruction boudary check with CONFIG_RETHUNK
	tracing/hist: Fix wrong return value in parse_action_params()
	tracing: Fix infinite loop in tracing_read_pipe on overflowed print_trace_line
	staging: media: tegra-video: fix chan->mipi value on error
	ARM: 9256/1: NWFPE: avoid compiler-generated __aeabi_uldivmod
	media: dvb-core: Fix double free in dvb_register_device()
	media: dvb-core: Fix UAF due to refcount races at releasing
	cifs: fix confusing debug message
	cifs: fix missing display of three mount options
	rtc: ds1347: fix value written to century register
	md/bitmap: Fix bitmap chunk size overflow issues
	efi: Add iMac Pro 2017 to uefi skip cert quirk
	wifi: wilc1000: sdio: fix module autoloading
	ASoC: jz4740-i2s: Handle independent FIFO flush bits
	ipmi: fix long wait in unload when IPMI disconnect
	mtd: spi-nor: Check for zero erase size in spi_nor_find_best_erase_type()
	ima: Fix a potential NULL pointer access in ima_restore_measurement_list
	ipmi: fix use after free in _ipmi_destroy_user()
	PCI: Fix pci_device_is_present() for VFs by checking PF
	PCI/sysfs: Fix double free in error path
	crypto: n2 - add missing hash statesize
	driver core: Fix bus_type.match() error handling in __driver_attach()
	iommu/amd: Fix ivrs_acpihid cmdline parsing code
	remoteproc: core: Do pm_relax when in RPROC_OFFLINE state
	parisc: led: Fix potential null-ptr-deref in start_task()
	device_cgroup: Roll back to original exceptions after copy failure
	drm/connector: send hotplug uevent on connector cleanup
	drm/vmwgfx: Validate the box size for the snooped cursor
	drm/i915/dsi: fix VBT send packet port selection for dual link DSI
	drm/ingenic: Fix missing platform_driver_unregister() call in ingenic_drm_init()
	ext4: silence the warning when evicting inode with dioread_nolock
	ext4: add inode table check in __ext4_get_inode_loc to aovid possible infinite loop
	ext4: fix use-after-free in ext4_orphan_cleanup
	ext4: fix undefined behavior in bit shift for ext4_check_flag_values
	ext4: add EXT4_IGET_BAD flag to prevent unexpected bad inode
	ext4: add helper to check quota inums
	ext4: fix bug_on in __es_tree_search caused by bad quota inode
	ext4: fix reserved cluster accounting in __es_remove_extent()
	ext4: check and assert if marking an no_delete evicting inode dirty
	ext4: fix bug_on in __es_tree_search caused by bad boot loader inode
	ext4: init quota for 'old.inode' in 'ext4_rename'
	ext4: fix delayed allocation bug in ext4_clu_mapped for bigalloc + inline
	ext4: fix corruption when online resizing a 1K bigalloc fs
	ext4: fix error code return to user-space in ext4_get_branch()
	ext4: avoid BUG_ON when creating xattrs
	ext4: fix inode leak in ext4_xattr_inode_create() on an error path
	ext4: initialize quota before expanding inode in setproject ioctl
	ext4: avoid unaccounted block allocation when expanding inode
	ext4: allocate extended attribute value in vmalloc area
	drm/amdgpu: handle polaris10/11 overlap asics (v2)
	drm/amdgpu: make display pinning more flexible (v2)
	ARM: renumber bits related to _TIF_WORK_MASK
	perf/x86/intel/uncore: Generalize I/O stacks to PMON mapping procedure
	perf/x86/intel/uncore: Clear attr_update properly
	btrfs: replace strncpy() with strscpy()
	x86/mce: Get rid of msr_ops
	x86/MCE/AMD: Clear DFR errors found in THR handler
	media: s5p-mfc: Fix to handle reference queue during finishing
	media: s5p-mfc: Clear workbit to handle error condition
	media: s5p-mfc: Fix in register read and write for H264
	perf probe: Use dwarf_attr_integrate as generic DWARF attr accessor
	perf probe: Fix to get the DW_AT_decl_file and DW_AT_call_file as unsinged data
	x86/kprobes: Convert to insn_decode()
	x86/kprobes: Fix optprobe optimization check with CONFIG_RETHUNK
	staging: media: tegra-video: fix device_node use after free
	ravb: Fix "failed to switch device to config mode" message during unbind
	riscv/stacktrace: Fix stack output without ra on the stack top
	riscv: stacktrace: Fixup ftrace_graph_ret_addr retp argument
	ext4: goto right label 'failed_mount3a'
	ext4: correct inconsistent error msg in nojournal mode
	mm/highmem: Lift memcpy_[to|from]_page to core
	ext4: use memcpy_to_page() in pagecache_write()
	fs: ext4: initialize fsdata in pagecache_write()
	ext4: move functions in super.c
	ext4: simplify ext4 error translation
	ext4: fix various seppling typos
	ext4: fix leaking uninitialized memory in fast-commit journal
	ext4: use kmemdup() to replace kmalloc + memcpy
	mbcache: don't reclaim used entries
	mbcache: add functions to delete entry if unused
	ext4: remove EA inode entry from mbcache on inode eviction
	ext4: unindent codeblock in ext4_xattr_block_set()
	ext4: fix race when reusing xattr blocks
	mbcache: automatically delete entries from cache on freeing
	ext4: fix deadlock due to mbcache entry corruption
	SUNRPC: ensure the matching upcall is in-flight upon downcall
	bpf: pull before calling skb_postpull_rcsum()
	drm/panfrost: Fix GEM handle creation ref-counting
	vmxnet3: correctly report csum_level for encapsulated packet
	veth: Fix race with AF_XDP exposing old or uninitialized descriptors
	nfsd: shut down the NFSv4 state objects before the filecache
	net: hns3: add interrupts re-initialization while doing VF FLR
	net: sched: fix memory leak in tcindex_set_parms
	qlcnic: prevent ->dcb use-after-free on qlcnic_dcb_enable() failure
	nfc: Fix potential resource leaks
	vhost/vsock: Fix error handling in vhost_vsock_init()
	vringh: fix range used in iotlb_translate()
	vhost: fix range used in translate_desc()
	net/mlx5: Add forgotten cleanup calls into mlx5_init_once() error path
	net/mlx5: Avoid recovery in probe flows
	net/mlx5e: IPoIB, Don't allow CQE compression to be turned on by default
	net/mlx5e: Fix hw mtu initializing at XDP SQ allocation
	net: amd-xgbe: add missed tasklet_kill
	net: phy: xgmiitorgmii: Fix refcount leak in xgmiitorgmii_probe
	RDMA/mlx5: Fix validation of max_rd_atomic caps for DC
	drm/meson: Reduce the FIFO lines held when AFBC is not used
	filelock: new helper: vfs_inode_has_locks
	ceph: switch to vfs_inode_has_locks() to fix file lock bug
	gpio: sifive: Fix refcount leak in sifive_gpio_probe
	net: sched: atm: dont intepret cls results when asked to drop
	net: sched: cbq: dont intepret cls results when asked to drop
	netfilter: ipset: fix hash:net,port,net hang with /0 subnet
	netfilter: ipset: Rework long task execution when adding/deleting entries
	perf tools: Fix resources leak in perf_data__open_dir()
	drivers/net/bonding/bond_3ad: return when there's no aggregator
	usb: rndis_host: Secure rndis_query check against int overflow
	drm/i915: unpin on error in intel_vgpu_shadow_mm_pin()
	caif: fix memory leak in cfctrl_linkup_request()
	udf: Fix extension of the last extent in the file
	ASoC: Intel: bytcr_rt5640: Add quirk for the Advantech MICA-071 tablet
	nvme: fix multipath crash caused by flush request when blktrace is enabled
	x86/bugs: Flush IBP in ib_prctl_set()
	nfsd: fix handling of readdir in v4root vs. mount upcall timeout
	fbdev: matroxfb: G200eW: Increase max memory from 1 MB to 16 MB
	riscv: uaccess: fix type of 0 variable on error in get_user()
	drm/i915/gvt: fix gvt debugfs destroy
	drm/i915/gvt: fix vgpu debugfs clean in remove
	ext4: don't allow journal inode to have encrypt flag
	selftests: set the BUILD variable to absolute path
	hfs/hfsplus: use WARN_ON for sanity check
	hfs/hfsplus: avoid WARN_ON() for sanity check, use proper error handling
	mbcache: Avoid nesting of cache->c_list_lock under bit locks
	efi: random: combine bootloader provided RNG seed with RNG protocol output
	io_uring: Fix unsigned 'res' comparison with zero in io_fixup_rw_res()
	parisc: Align parisc MADV_XXX constants with all other architectures
	ext4: disable fast-commit of encrypted dir operations
	ext4: don't set up encryption key during jbd2 transaction
	fsl_lpuart: Don't enable interrupts too early
	serial: fixup backport of "serial: Deassert Transmit Enable on probe in driver-specific way"
	mptcp: mark ops structures as ro_after_init
	mptcp: remove MPTCP 'ifdef' in TCP SYN cookies
	mptcp: dedicated request sock for subflow in v6
	mptcp: use proper req destructor for IPv6
	net: sched: disallow noqueue for qdisc classes
	net/ulp: prevent ULP without clone op from entering the LISTEN status
	ALSA: pcm: Move rwsem lock inside snd_ctl_elem_read to prevent UAF
	ALSA: hda/hdmi: Add a HP device 0x8715 to force connect list
	ALSA: hda - Enable headset mic on another Dell laptop with ALC3254
	Linux 5.10.163

Change-Id: I9026971760be8484f1e1fa607f9f91243cc87785
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2023-02-06 12:30:05 +00:00

2721 lines
72 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* linux/kernel/power/snapshot.c
*
* This file provides system snapshot/restore functionality for swsusp.
*
* Copyright (C) 1998-2005 Pavel Machek <pavel@ucw.cz>
* Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
*/
#define pr_fmt(fmt) "PM: hibernation: " fmt
#include <linux/version.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/suspend.h>
#include <linux/delay.h>
#include <linux/bitops.h>
#include <linux/spinlock.h>
#include <linux/kernel.h>
#include <linux/pm.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/memblock.h>
#include <linux/nmi.h>
#include <linux/syscalls.h>
#include <linux/console.h>
#include <linux/highmem.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/compiler.h>
#include <linux/ktime.h>
#include <linux/set_memory.h>
#include <linux/uaccess.h>
#include <asm/mmu_context.h>
#include <asm/tlbflush.h>
#include <asm/io.h>
#include "power.h"
#if defined(CONFIG_STRICT_KERNEL_RWX) && defined(CONFIG_ARCH_HAS_SET_MEMORY)
static bool hibernate_restore_protection;
static bool hibernate_restore_protection_active;
void enable_restore_image_protection(void)
{
hibernate_restore_protection = true;
}
static inline void hibernate_restore_protection_begin(void)
{
hibernate_restore_protection_active = hibernate_restore_protection;
}
static inline void hibernate_restore_protection_end(void)
{
hibernate_restore_protection_active = false;
}
static inline void hibernate_restore_protect_page(void *page_address)
{
if (hibernate_restore_protection_active)
set_memory_ro((unsigned long)page_address, 1);
}
static inline void hibernate_restore_unprotect_page(void *page_address)
{
if (hibernate_restore_protection_active)
set_memory_rw((unsigned long)page_address, 1);
}
#else
static inline void hibernate_restore_protection_begin(void) {}
static inline void hibernate_restore_protection_end(void) {}
static inline void hibernate_restore_protect_page(void *page_address) {}
static inline void hibernate_restore_unprotect_page(void *page_address) {}
#endif /* CONFIG_STRICT_KERNEL_RWX && CONFIG_ARCH_HAS_SET_MEMORY */
static int swsusp_page_is_free(struct page *);
static void swsusp_set_page_forbidden(struct page *);
static void swsusp_unset_page_forbidden(struct page *);
/*
* Number of bytes to reserve for memory allocations made by device drivers
* from their ->freeze() and ->freeze_noirq() callbacks so that they don't
* cause image creation to fail (tunable via /sys/power/reserved_size).
*/
unsigned long reserved_size;
void __init hibernate_reserved_size_init(void)
{
reserved_size = SPARE_PAGES * PAGE_SIZE;
}
/*
* Preferred image size in bytes (tunable via /sys/power/image_size).
* When it is set to N, swsusp will do its best to ensure the image
* size will not exceed N bytes, but if that is impossible, it will
* try to create the smallest image possible.
*/
unsigned long image_size;
void __init hibernate_image_size_init(void)
{
image_size = ((totalram_pages() * 2) / 5) * PAGE_SIZE;
}
/*
* List of PBEs needed for restoring the pages that were allocated before
* the suspend and included in the suspend image, but have also been
* allocated by the "resume" kernel, so their contents cannot be written
* directly to their "original" page frames.
*/
struct pbe *restore_pblist;
/* struct linked_page is used to build chains of pages */
#define LINKED_PAGE_DATA_SIZE (PAGE_SIZE - sizeof(void *))
struct linked_page {
struct linked_page *next;
char data[LINKED_PAGE_DATA_SIZE];
} __packed;
/*
* List of "safe" pages (ie. pages that were not used by the image kernel
* before hibernation) that may be used as temporary storage for image kernel
* memory contents.
*/
static struct linked_page *safe_pages_list;
/* Pointer to an auxiliary buffer (1 page) */
static void *buffer;
#define PG_ANY 0
#define PG_SAFE 1
#define PG_UNSAFE_CLEAR 1
#define PG_UNSAFE_KEEP 0
static unsigned int allocated_unsafe_pages;
/**
* get_image_page - Allocate a page for a hibernation image.
* @gfp_mask: GFP mask for the allocation.
* @safe_needed: Get pages that were not used before hibernation (restore only)
*
* During image restoration, for storing the PBE list and the image data, we can
* only use memory pages that do not conflict with the pages used before
* hibernation. The "unsafe" pages have PageNosaveFree set and we count them
* using allocated_unsafe_pages.
*
* Each allocated image page is marked as PageNosave and PageNosaveFree so that
* swsusp_free() can release it.
*/
static void *get_image_page(gfp_t gfp_mask, int safe_needed)
{
void *res;
res = (void *)get_zeroed_page(gfp_mask);
if (safe_needed)
while (res && swsusp_page_is_free(virt_to_page(res))) {
/* The page is unsafe, mark it for swsusp_free() */
swsusp_set_page_forbidden(virt_to_page(res));
allocated_unsafe_pages++;
res = (void *)get_zeroed_page(gfp_mask);
}
if (res) {
swsusp_set_page_forbidden(virt_to_page(res));
swsusp_set_page_free(virt_to_page(res));
}
return res;
}
static void *__get_safe_page(gfp_t gfp_mask)
{
if (safe_pages_list) {
void *ret = safe_pages_list;
safe_pages_list = safe_pages_list->next;
memset(ret, 0, PAGE_SIZE);
return ret;
}
return get_image_page(gfp_mask, PG_SAFE);
}
unsigned long get_safe_page(gfp_t gfp_mask)
{
return (unsigned long)__get_safe_page(gfp_mask);
}
static struct page *alloc_image_page(gfp_t gfp_mask)
{
struct page *page;
page = alloc_page(gfp_mask);
if (page) {
swsusp_set_page_forbidden(page);
swsusp_set_page_free(page);
}
return page;
}
static void recycle_safe_page(void *page_address)
{
struct linked_page *lp = page_address;
lp->next = safe_pages_list;
safe_pages_list = lp;
}
/**
* free_image_page - Free a page allocated for hibernation image.
* @addr: Address of the page to free.
* @clear_nosave_free: If set, clear the PageNosaveFree bit for the page.
*
* The page to free should have been allocated by get_image_page() (page flags
* set by it are affected).
*/
static inline void free_image_page(void *addr, int clear_nosave_free)
{
struct page *page;
BUG_ON(!virt_addr_valid(addr));
page = virt_to_page(addr);
swsusp_unset_page_forbidden(page);
if (clear_nosave_free)
swsusp_unset_page_free(page);
__free_page(page);
}
static inline void free_list_of_pages(struct linked_page *list,
int clear_page_nosave)
{
while (list) {
struct linked_page *lp = list->next;
free_image_page(list, clear_page_nosave);
list = lp;
}
}
/*
* struct chain_allocator is used for allocating small objects out of
* a linked list of pages called 'the chain'.
*
* The chain grows each time when there is no room for a new object in
* the current page. The allocated objects cannot be freed individually.
* It is only possible to free them all at once, by freeing the entire
* chain.
*
* NOTE: The chain allocator may be inefficient if the allocated objects
* are not much smaller than PAGE_SIZE.
*/
struct chain_allocator {
struct linked_page *chain; /* the chain */
unsigned int used_space; /* total size of objects allocated out
of the current page */
gfp_t gfp_mask; /* mask for allocating pages */
int safe_needed; /* if set, only "safe" pages are allocated */
};
static void chain_init(struct chain_allocator *ca, gfp_t gfp_mask,
int safe_needed)
{
ca->chain = NULL;
ca->used_space = LINKED_PAGE_DATA_SIZE;
ca->gfp_mask = gfp_mask;
ca->safe_needed = safe_needed;
}
static void *chain_alloc(struct chain_allocator *ca, unsigned int size)
{
void *ret;
if (LINKED_PAGE_DATA_SIZE - ca->used_space < size) {
struct linked_page *lp;
lp = ca->safe_needed ? __get_safe_page(ca->gfp_mask) :
get_image_page(ca->gfp_mask, PG_ANY);
if (!lp)
return NULL;
lp->next = ca->chain;
ca->chain = lp;
ca->used_space = 0;
}
ret = ca->chain->data + ca->used_space;
ca->used_space += size;
return ret;
}
/**
* Data types related to memory bitmaps.
*
* Memory bitmap is a structure consiting of many linked lists of
* objects. The main list's elements are of type struct zone_bitmap
* and each of them corresonds to one zone. For each zone bitmap
* object there is a list of objects of type struct bm_block that
* represent each blocks of bitmap in which information is stored.
*
* struct memory_bitmap contains a pointer to the main list of zone
* bitmap objects, a struct bm_position used for browsing the bitmap,
* and a pointer to the list of pages used for allocating all of the
* zone bitmap objects and bitmap block objects.
*
* NOTE: It has to be possible to lay out the bitmap in memory
* using only allocations of order 0. Additionally, the bitmap is
* designed to work with arbitrary number of zones (this is over the
* top for now, but let's avoid making unnecessary assumptions ;-).
*
* struct zone_bitmap contains a pointer to a list of bitmap block
* objects and a pointer to the bitmap block object that has been
* most recently used for setting bits. Additionally, it contains the
* PFNs that correspond to the start and end of the represented zone.
*
* struct bm_block contains a pointer to the memory page in which
* information is stored (in the form of a block of bitmap)
* It also contains the pfns that correspond to the start and end of
* the represented memory area.
*
* The memory bitmap is organized as a radix tree to guarantee fast random
* access to the bits. There is one radix tree for each zone (as returned
* from create_mem_extents).
*
* One radix tree is represented by one struct mem_zone_bm_rtree. There are
* two linked lists for the nodes of the tree, one for the inner nodes and
* one for the leave nodes. The linked leave nodes are used for fast linear
* access of the memory bitmap.
*
* The struct rtree_node represents one node of the radix tree.
*/
#define BM_END_OF_MAP (~0UL)
#define BM_BITS_PER_BLOCK (PAGE_SIZE * BITS_PER_BYTE)
#define BM_BLOCK_SHIFT (PAGE_SHIFT + 3)
#define BM_BLOCK_MASK ((1UL << BM_BLOCK_SHIFT) - 1)
/*
* struct rtree_node is a wrapper struct to link the nodes
* of the rtree together for easy linear iteration over
* bits and easy freeing
*/
struct rtree_node {
struct list_head list;
unsigned long *data;
};
/*
* struct mem_zone_bm_rtree represents a bitmap used for one
* populated memory zone.
*/
struct mem_zone_bm_rtree {
struct list_head list; /* Link Zones together */
struct list_head nodes; /* Radix Tree inner nodes */
struct list_head leaves; /* Radix Tree leaves */
unsigned long start_pfn; /* Zone start page frame */
unsigned long end_pfn; /* Zone end page frame + 1 */
struct rtree_node *rtree; /* Radix Tree Root */
int levels; /* Number of Radix Tree Levels */
unsigned int blocks; /* Number of Bitmap Blocks */
};
/* strcut bm_position is used for browsing memory bitmaps */
struct bm_position {
struct mem_zone_bm_rtree *zone;
struct rtree_node *node;
unsigned long node_pfn;
int node_bit;
};
struct memory_bitmap {
struct list_head zones;
struct linked_page *p_list; /* list of pages used to store zone
bitmap objects and bitmap block
objects */
struct bm_position cur; /* most recently used bit position */
};
/* Functions that operate on memory bitmaps */
#define BM_ENTRIES_PER_LEVEL (PAGE_SIZE / sizeof(unsigned long))
#if BITS_PER_LONG == 32
#define BM_RTREE_LEVEL_SHIFT (PAGE_SHIFT - 2)
#else
#define BM_RTREE_LEVEL_SHIFT (PAGE_SHIFT - 3)
#endif
#define BM_RTREE_LEVEL_MASK ((1UL << BM_RTREE_LEVEL_SHIFT) - 1)
/**
* alloc_rtree_node - Allocate a new node and add it to the radix tree.
*
* This function is used to allocate inner nodes as well as the
* leave nodes of the radix tree. It also adds the node to the
* corresponding linked list passed in by the *list parameter.
*/
static struct rtree_node *alloc_rtree_node(gfp_t gfp_mask, int safe_needed,
struct chain_allocator *ca,
struct list_head *list)
{
struct rtree_node *node;
node = chain_alloc(ca, sizeof(struct rtree_node));
if (!node)
return NULL;
node->data = get_image_page(gfp_mask, safe_needed);
if (!node->data)
return NULL;
list_add_tail(&node->list, list);
return node;
}
/**
* add_rtree_block - Add a new leave node to the radix tree.
*
* The leave nodes need to be allocated in order to keep the leaves
* linked list in order. This is guaranteed by the zone->blocks
* counter.
*/
static int add_rtree_block(struct mem_zone_bm_rtree *zone, gfp_t gfp_mask,
int safe_needed, struct chain_allocator *ca)
{
struct rtree_node *node, *block, **dst;
unsigned int levels_needed, block_nr;
int i;
block_nr = zone->blocks;
levels_needed = 0;
/* How many levels do we need for this block nr? */
while (block_nr) {
levels_needed += 1;
block_nr >>= BM_RTREE_LEVEL_SHIFT;
}
/* Make sure the rtree has enough levels */
for (i = zone->levels; i < levels_needed; i++) {
node = alloc_rtree_node(gfp_mask, safe_needed, ca,
&zone->nodes);
if (!node)
return -ENOMEM;
node->data[0] = (unsigned long)zone->rtree;
zone->rtree = node;
zone->levels += 1;
}
/* Allocate new block */
block = alloc_rtree_node(gfp_mask, safe_needed, ca, &zone->leaves);
if (!block)
return -ENOMEM;
/* Now walk the rtree to insert the block */
node = zone->rtree;
dst = &zone->rtree;
block_nr = zone->blocks;
for (i = zone->levels; i > 0; i--) {
int index;
if (!node) {
node = alloc_rtree_node(gfp_mask, safe_needed, ca,
&zone->nodes);
if (!node)
return -ENOMEM;
*dst = node;
}
index = block_nr >> ((i - 1) * BM_RTREE_LEVEL_SHIFT);
index &= BM_RTREE_LEVEL_MASK;
dst = (struct rtree_node **)&((*dst)->data[index]);
node = *dst;
}
zone->blocks += 1;
*dst = block;
return 0;
}
static void free_zone_bm_rtree(struct mem_zone_bm_rtree *zone,
int clear_nosave_free);
/**
* create_zone_bm_rtree - Create a radix tree for one zone.
*
* Allocated the mem_zone_bm_rtree structure and initializes it.
* This function also allocated and builds the radix tree for the
* zone.
*/
static struct mem_zone_bm_rtree *create_zone_bm_rtree(gfp_t gfp_mask,
int safe_needed,
struct chain_allocator *ca,
unsigned long start,
unsigned long end)
{
struct mem_zone_bm_rtree *zone;
unsigned int i, nr_blocks;
unsigned long pages;
pages = end - start;
zone = chain_alloc(ca, sizeof(struct mem_zone_bm_rtree));
if (!zone)
return NULL;
INIT_LIST_HEAD(&zone->nodes);
INIT_LIST_HEAD(&zone->leaves);
zone->start_pfn = start;
zone->end_pfn = end;
nr_blocks = DIV_ROUND_UP(pages, BM_BITS_PER_BLOCK);
for (i = 0; i < nr_blocks; i++) {
if (add_rtree_block(zone, gfp_mask, safe_needed, ca)) {
free_zone_bm_rtree(zone, PG_UNSAFE_CLEAR);
return NULL;
}
}
return zone;
}
/**
* free_zone_bm_rtree - Free the memory of the radix tree.
*
* Free all node pages of the radix tree. The mem_zone_bm_rtree
* structure itself is not freed here nor are the rtree_node
* structs.
*/
static void free_zone_bm_rtree(struct mem_zone_bm_rtree *zone,
int clear_nosave_free)
{
struct rtree_node *node;
list_for_each_entry(node, &zone->nodes, list)
free_image_page(node->data, clear_nosave_free);
list_for_each_entry(node, &zone->leaves, list)
free_image_page(node->data, clear_nosave_free);
}
static void memory_bm_position_reset(struct memory_bitmap *bm)
{
bm->cur.zone = list_entry(bm->zones.next, struct mem_zone_bm_rtree,
list);
bm->cur.node = list_entry(bm->cur.zone->leaves.next,
struct rtree_node, list);
bm->cur.node_pfn = 0;
bm->cur.node_bit = 0;
}
static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free);
struct mem_extent {
struct list_head hook;
unsigned long start;
unsigned long end;
};
/**
* free_mem_extents - Free a list of memory extents.
* @list: List of extents to free.
*/
static void free_mem_extents(struct list_head *list)
{
struct mem_extent *ext, *aux;
list_for_each_entry_safe(ext, aux, list, hook) {
list_del(&ext->hook);
kfree(ext);
}
}
/**
* create_mem_extents - Create a list of memory extents.
* @list: List to put the extents into.
* @gfp_mask: Mask to use for memory allocations.
*
* The extents represent contiguous ranges of PFNs.
*/
static int create_mem_extents(struct list_head *list, gfp_t gfp_mask)
{
struct zone *zone;
INIT_LIST_HEAD(list);
for_each_populated_zone(zone) {
unsigned long zone_start, zone_end;
struct mem_extent *ext, *cur, *aux;
zone_start = zone->zone_start_pfn;
zone_end = zone_end_pfn(zone);
list_for_each_entry(ext, list, hook)
if (zone_start <= ext->end)
break;
if (&ext->hook == list || zone_end < ext->start) {
/* New extent is necessary */
struct mem_extent *new_ext;
new_ext = kzalloc(sizeof(struct mem_extent), gfp_mask);
if (!new_ext) {
free_mem_extents(list);
return -ENOMEM;
}
new_ext->start = zone_start;
new_ext->end = zone_end;
list_add_tail(&new_ext->hook, &ext->hook);
continue;
}
/* Merge this zone's range of PFNs with the existing one */
if (zone_start < ext->start)
ext->start = zone_start;
if (zone_end > ext->end)
ext->end = zone_end;
/* More merging may be possible */
cur = ext;
list_for_each_entry_safe_continue(cur, aux, list, hook) {
if (zone_end < cur->start)
break;
if (zone_end < cur->end)
ext->end = cur->end;
list_del(&cur->hook);
kfree(cur);
}
}
return 0;
}
/**
* memory_bm_create - Allocate memory for a memory bitmap.
*/
static int memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask,
int safe_needed)
{
struct chain_allocator ca;
struct list_head mem_extents;
struct mem_extent *ext;
int error;
chain_init(&ca, gfp_mask, safe_needed);
INIT_LIST_HEAD(&bm->zones);
error = create_mem_extents(&mem_extents, gfp_mask);
if (error)
return error;
list_for_each_entry(ext, &mem_extents, hook) {
struct mem_zone_bm_rtree *zone;
zone = create_zone_bm_rtree(gfp_mask, safe_needed, &ca,
ext->start, ext->end);
if (!zone) {
error = -ENOMEM;
goto Error;
}
list_add_tail(&zone->list, &bm->zones);
}
bm->p_list = ca.chain;
memory_bm_position_reset(bm);
Exit:
free_mem_extents(&mem_extents);
return error;
Error:
bm->p_list = ca.chain;
memory_bm_free(bm, PG_UNSAFE_CLEAR);
goto Exit;
}
/**
* memory_bm_free - Free memory occupied by the memory bitmap.
* @bm: Memory bitmap.
*/
static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free)
{
struct mem_zone_bm_rtree *zone;
list_for_each_entry(zone, &bm->zones, list)
free_zone_bm_rtree(zone, clear_nosave_free);
free_list_of_pages(bm->p_list, clear_nosave_free);
INIT_LIST_HEAD(&bm->zones);
}
/**
* memory_bm_find_bit - Find the bit for a given PFN in a memory bitmap.
*
* Find the bit in memory bitmap @bm that corresponds to the given PFN.
* The cur.zone, cur.block and cur.node_pfn members of @bm are updated.
*
* Walk the radix tree to find the page containing the bit that represents @pfn
* and return the position of the bit in @addr and @bit_nr.
*/
static int memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
void **addr, unsigned int *bit_nr)
{
struct mem_zone_bm_rtree *curr, *zone;
struct rtree_node *node;
int i, block_nr;
zone = bm->cur.zone;
if (pfn >= zone->start_pfn && pfn < zone->end_pfn)
goto zone_found;
zone = NULL;
/* Find the right zone */
list_for_each_entry(curr, &bm->zones, list) {
if (pfn >= curr->start_pfn && pfn < curr->end_pfn) {
zone = curr;
break;
}
}
if (!zone)
return -EFAULT;
zone_found:
/*
* We have found the zone. Now walk the radix tree to find the leaf node
* for our PFN.
*/
/*
* If the zone we wish to scan is the current zone and the
* pfn falls into the current node then we do not need to walk
* the tree.
*/
node = bm->cur.node;
if (zone == bm->cur.zone &&
((pfn - zone->start_pfn) & ~BM_BLOCK_MASK) == bm->cur.node_pfn)
goto node_found;
node = zone->rtree;
block_nr = (pfn - zone->start_pfn) >> BM_BLOCK_SHIFT;
for (i = zone->levels; i > 0; i--) {
int index;
index = block_nr >> ((i - 1) * BM_RTREE_LEVEL_SHIFT);
index &= BM_RTREE_LEVEL_MASK;
BUG_ON(node->data[index] == 0);
node = (struct rtree_node *)node->data[index];
}
node_found:
/* Update last position */
bm->cur.zone = zone;
bm->cur.node = node;
bm->cur.node_pfn = (pfn - zone->start_pfn) & ~BM_BLOCK_MASK;
/* Set return values */
*addr = node->data;
*bit_nr = (pfn - zone->start_pfn) & BM_BLOCK_MASK;
return 0;
}
static void memory_bm_set_bit(struct memory_bitmap *bm, unsigned long pfn)
{
void *addr;
unsigned int bit;
int error;
error = memory_bm_find_bit(bm, pfn, &addr, &bit);
BUG_ON(error);
set_bit(bit, addr);
}
static int mem_bm_set_bit_check(struct memory_bitmap *bm, unsigned long pfn)
{
void *addr;
unsigned int bit;
int error;
error = memory_bm_find_bit(bm, pfn, &addr, &bit);
if (!error)
set_bit(bit, addr);
return error;
}
static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn)
{
void *addr;
unsigned int bit;
int error;
error = memory_bm_find_bit(bm, pfn, &addr, &bit);
BUG_ON(error);
clear_bit(bit, addr);
}
static void memory_bm_clear_current(struct memory_bitmap *bm)
{
int bit;
bit = max(bm->cur.node_bit - 1, 0);
clear_bit(bit, bm->cur.node->data);
}
static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn)
{
void *addr;
unsigned int bit;
int error;
error = memory_bm_find_bit(bm, pfn, &addr, &bit);
BUG_ON(error);
return test_bit(bit, addr);
}
static bool memory_bm_pfn_present(struct memory_bitmap *bm, unsigned long pfn)
{
void *addr;
unsigned int bit;
return !memory_bm_find_bit(bm, pfn, &addr, &bit);
}
/*
* rtree_next_node - Jump to the next leaf node.
*
* Set the position to the beginning of the next node in the
* memory bitmap. This is either the next node in the current
* zone's radix tree or the first node in the radix tree of the
* next zone.
*
* Return true if there is a next node, false otherwise.
*/
static bool rtree_next_node(struct memory_bitmap *bm)
{
if (!list_is_last(&bm->cur.node->list, &bm->cur.zone->leaves)) {
bm->cur.node = list_entry(bm->cur.node->list.next,
struct rtree_node, list);
bm->cur.node_pfn += BM_BITS_PER_BLOCK;
bm->cur.node_bit = 0;
touch_softlockup_watchdog();
return true;
}
/* No more nodes, goto next zone */
if (!list_is_last(&bm->cur.zone->list, &bm->zones)) {
bm->cur.zone = list_entry(bm->cur.zone->list.next,
struct mem_zone_bm_rtree, list);
bm->cur.node = list_entry(bm->cur.zone->leaves.next,
struct rtree_node, list);
bm->cur.node_pfn = 0;
bm->cur.node_bit = 0;
return true;
}
/* No more zones */
return false;
}
/**
* memory_bm_rtree_next_pfn - Find the next set bit in a memory bitmap.
* @bm: Memory bitmap.
*
* Starting from the last returned position this function searches for the next
* set bit in @bm and returns the PFN represented by it. If no more bits are
* set, BM_END_OF_MAP is returned.
*
* It is required to run memory_bm_position_reset() before the first call to
* this function for the given memory bitmap.
*/
static unsigned long memory_bm_next_pfn(struct memory_bitmap *bm)
{
unsigned long bits, pfn, pages;
int bit;
do {
pages = bm->cur.zone->end_pfn - bm->cur.zone->start_pfn;
bits = min(pages - bm->cur.node_pfn, BM_BITS_PER_BLOCK);
bit = find_next_bit(bm->cur.node->data, bits,
bm->cur.node_bit);
if (bit < bits) {
pfn = bm->cur.zone->start_pfn + bm->cur.node_pfn + bit;
bm->cur.node_bit = bit + 1;
return pfn;
}
} while (rtree_next_node(bm));
return BM_END_OF_MAP;
}
/*
* This structure represents a range of page frames the contents of which
* should not be saved during hibernation.
*/
struct nosave_region {
struct list_head list;
unsigned long start_pfn;
unsigned long end_pfn;
};
static LIST_HEAD(nosave_regions);
static void recycle_zone_bm_rtree(struct mem_zone_bm_rtree *zone)
{
struct rtree_node *node;
list_for_each_entry(node, &zone->nodes, list)
recycle_safe_page(node->data);
list_for_each_entry(node, &zone->leaves, list)
recycle_safe_page(node->data);
}
static void memory_bm_recycle(struct memory_bitmap *bm)
{
struct mem_zone_bm_rtree *zone;
struct linked_page *p_list;
list_for_each_entry(zone, &bm->zones, list)
recycle_zone_bm_rtree(zone);
p_list = bm->p_list;
while (p_list) {
struct linked_page *lp = p_list;
p_list = lp->next;
recycle_safe_page(lp);
}
}
/**
* register_nosave_region - Register a region of unsaveable memory.
*
* Register a range of page frames the contents of which should not be saved
* during hibernation (to be used in the early initialization code).
*/
void __init register_nosave_region(unsigned long start_pfn, unsigned long end_pfn)
{
struct nosave_region *region;
if (start_pfn >= end_pfn)
return;
if (!list_empty(&nosave_regions)) {
/* Try to extend the previous region (they should be sorted) */
region = list_entry(nosave_regions.prev,
struct nosave_region, list);
if (region->end_pfn == start_pfn) {
region->end_pfn = end_pfn;
goto Report;
}
}
/* This allocation cannot fail */
region = memblock_alloc(sizeof(struct nosave_region),
SMP_CACHE_BYTES);
if (!region)
panic("%s: Failed to allocate %zu bytes\n", __func__,
sizeof(struct nosave_region));
region->start_pfn = start_pfn;
region->end_pfn = end_pfn;
list_add_tail(&region->list, &nosave_regions);
Report:
pr_info("Registered nosave memory: [mem %#010llx-%#010llx]\n",
(unsigned long long) start_pfn << PAGE_SHIFT,
((unsigned long long) end_pfn << PAGE_SHIFT) - 1);
}
/*
* Set bits in this map correspond to the page frames the contents of which
* should not be saved during the suspend.
*/
static struct memory_bitmap *forbidden_pages_map;
/* Set bits in this map correspond to free page frames. */
static struct memory_bitmap *free_pages_map;
/*
* Each page frame allocated for creating the image is marked by setting the
* corresponding bits in forbidden_pages_map and free_pages_map simultaneously
*/
void swsusp_set_page_free(struct page *page)
{
if (free_pages_map)
memory_bm_set_bit(free_pages_map, page_to_pfn(page));
}
static int swsusp_page_is_free(struct page *page)
{
return free_pages_map ?
memory_bm_test_bit(free_pages_map, page_to_pfn(page)) : 0;
}
void swsusp_unset_page_free(struct page *page)
{
if (free_pages_map)
memory_bm_clear_bit(free_pages_map, page_to_pfn(page));
}
static void swsusp_set_page_forbidden(struct page *page)
{
if (forbidden_pages_map)
memory_bm_set_bit(forbidden_pages_map, page_to_pfn(page));
}
int swsusp_page_is_forbidden(struct page *page)
{
return forbidden_pages_map ?
memory_bm_test_bit(forbidden_pages_map, page_to_pfn(page)) : 0;
}
static void swsusp_unset_page_forbidden(struct page *page)
{
if (forbidden_pages_map)
memory_bm_clear_bit(forbidden_pages_map, page_to_pfn(page));
}
/**
* mark_nosave_pages - Mark pages that should not be saved.
* @bm: Memory bitmap.
*
* Set the bits in @bm that correspond to the page frames the contents of which
* should not be saved.
*/
static void mark_nosave_pages(struct memory_bitmap *bm)
{
struct nosave_region *region;
if (list_empty(&nosave_regions))
return;
list_for_each_entry(region, &nosave_regions, list) {
unsigned long pfn;
pr_debug("Marking nosave pages: [mem %#010llx-%#010llx]\n",
(unsigned long long) region->start_pfn << PAGE_SHIFT,
((unsigned long long) region->end_pfn << PAGE_SHIFT)
- 1);
for (pfn = region->start_pfn; pfn < region->end_pfn; pfn++)
if (pfn_valid(pfn)) {
/*
* It is safe to ignore the result of
* mem_bm_set_bit_check() here, since we won't
* touch the PFNs for which the error is
* returned anyway.
*/
mem_bm_set_bit_check(bm, pfn);
}
}
}
/**
* create_basic_memory_bitmaps - Create bitmaps to hold basic page information.
*
* Create bitmaps needed for marking page frames that should not be saved and
* free page frames. The forbidden_pages_map and free_pages_map pointers are
* only modified if everything goes well, because we don't want the bits to be
* touched before both bitmaps are set up.
*/
int create_basic_memory_bitmaps(void)
{
struct memory_bitmap *bm1, *bm2;
int error = 0;
if (forbidden_pages_map && free_pages_map)
return 0;
else
BUG_ON(forbidden_pages_map || free_pages_map);
bm1 = kzalloc(sizeof(struct memory_bitmap), GFP_KERNEL);
if (!bm1)
return -ENOMEM;
error = memory_bm_create(bm1, GFP_KERNEL, PG_ANY);
if (error)
goto Free_first_object;
bm2 = kzalloc(sizeof(struct memory_bitmap), GFP_KERNEL);
if (!bm2)
goto Free_first_bitmap;
error = memory_bm_create(bm2, GFP_KERNEL, PG_ANY);
if (error)
goto Free_second_object;
forbidden_pages_map = bm1;
free_pages_map = bm2;
mark_nosave_pages(forbidden_pages_map);
pr_debug("Basic memory bitmaps created\n");
return 0;
Free_second_object:
kfree(bm2);
Free_first_bitmap:
memory_bm_free(bm1, PG_UNSAFE_CLEAR);
Free_first_object:
kfree(bm1);
return -ENOMEM;
}
/**
* free_basic_memory_bitmaps - Free memory bitmaps holding basic information.
*
* Free memory bitmaps allocated by create_basic_memory_bitmaps(). The
* auxiliary pointers are necessary so that the bitmaps themselves are not
* referred to while they are being freed.
*/
void free_basic_memory_bitmaps(void)
{
struct memory_bitmap *bm1, *bm2;
if (WARN_ON(!(forbidden_pages_map && free_pages_map)))
return;
bm1 = forbidden_pages_map;
bm2 = free_pages_map;
forbidden_pages_map = NULL;
free_pages_map = NULL;
memory_bm_free(bm1, PG_UNSAFE_CLEAR);
kfree(bm1);
memory_bm_free(bm2, PG_UNSAFE_CLEAR);
kfree(bm2);
pr_debug("Basic memory bitmaps freed\n");
}
static void clear_or_poison_free_page(struct page *page)
{
if (page_poisoning_enabled_static())
__kernel_poison_pages(page, 1);
else if (want_init_on_free())
clear_highpage(page);
}
void clear_or_poison_free_pages(void)
{
struct memory_bitmap *bm = free_pages_map;
unsigned long pfn;
if (WARN_ON(!(free_pages_map)))
return;
if (page_poisoning_enabled() || want_init_on_free()) {
memory_bm_position_reset(bm);
pfn = memory_bm_next_pfn(bm);
while (pfn != BM_END_OF_MAP) {
if (pfn_valid(pfn))
clear_or_poison_free_page(pfn_to_page(pfn));
pfn = memory_bm_next_pfn(bm);
}
memory_bm_position_reset(bm);
pr_info("free pages cleared after restore\n");
}
}
/**
* snapshot_additional_pages - Estimate the number of extra pages needed.
* @zone: Memory zone to carry out the computation for.
*
* Estimate the number of additional pages needed for setting up a hibernation
* image data structures for @zone (usually, the returned value is greater than
* the exact number).
*/
unsigned int snapshot_additional_pages(struct zone *zone)
{
unsigned int rtree, nodes;
rtree = nodes = DIV_ROUND_UP(zone->spanned_pages, BM_BITS_PER_BLOCK);
rtree += DIV_ROUND_UP(rtree * sizeof(struct rtree_node),
LINKED_PAGE_DATA_SIZE);
while (nodes > 1) {
nodes = DIV_ROUND_UP(nodes, BM_ENTRIES_PER_LEVEL);
rtree += nodes;
}
return 2 * rtree;
}
#ifdef CONFIG_HIGHMEM
/**
* count_free_highmem_pages - Compute the total number of free highmem pages.
*
* The returned number is system-wide.
*/
static unsigned int count_free_highmem_pages(void)
{
struct zone *zone;
unsigned int cnt = 0;
for_each_populated_zone(zone)
if (is_highmem(zone))
cnt += zone_page_state(zone, NR_FREE_PAGES);
return cnt;
}
/**
* saveable_highmem_page - Check if a highmem page is saveable.
*
* Determine whether a highmem page should be included in a hibernation image.
*
* We should save the page if it isn't Nosave or NosaveFree, or Reserved,
* and it isn't part of a free chunk of pages.
*/
static struct page *saveable_highmem_page(struct zone *zone, unsigned long pfn)
{
struct page *page;
if (!pfn_valid(pfn))
return NULL;
page = pfn_to_online_page(pfn);
if (!page || page_zone(page) != zone)
return NULL;
BUG_ON(!PageHighMem(page));
if (swsusp_page_is_forbidden(page) || swsusp_page_is_free(page))
return NULL;
if (PageReserved(page) || PageOffline(page))
return NULL;
if (page_is_guard(page))
return NULL;
return page;
}
/**
* count_highmem_pages - Compute the total number of saveable highmem pages.
*/
static unsigned int count_highmem_pages(void)
{
struct zone *zone;
unsigned int n = 0;
for_each_populated_zone(zone) {
unsigned long pfn, max_zone_pfn;
if (!is_highmem(zone))
continue;
mark_free_pages(zone);
max_zone_pfn = zone_end_pfn(zone);
for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
if (saveable_highmem_page(zone, pfn))
n++;
}
return n;
}
#else
static inline void *saveable_highmem_page(struct zone *z, unsigned long p)
{
return NULL;
}
#endif /* CONFIG_HIGHMEM */
/**
* saveable_page - Check if the given page is saveable.
*
* Determine whether a non-highmem page should be included in a hibernation
* image.
*
* We should save the page if it isn't Nosave, and is not in the range
* of pages statically defined as 'unsaveable', and it isn't part of
* a free chunk of pages.
*/
static struct page *saveable_page(struct zone *zone, unsigned long pfn)
{
struct page *page;
if (!pfn_valid(pfn))
return NULL;
page = pfn_to_online_page(pfn);
if (!page || page_zone(page) != zone)
return NULL;
BUG_ON(PageHighMem(page));
if (swsusp_page_is_forbidden(page) || swsusp_page_is_free(page))
return NULL;
if (PageOffline(page))
return NULL;
if (PageReserved(page)
&& (!kernel_page_present(page) || pfn_is_nosave(pfn)))
return NULL;
if (page_is_guard(page))
return NULL;
return page;
}
/**
* count_data_pages - Compute the total number of saveable non-highmem pages.
*/
static unsigned int count_data_pages(void)
{
struct zone *zone;
unsigned long pfn, max_zone_pfn;
unsigned int n = 0;
for_each_populated_zone(zone) {
if (is_highmem(zone))
continue;
mark_free_pages(zone);
max_zone_pfn = zone_end_pfn(zone);
for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
if (saveable_page(zone, pfn))
n++;
}
return n;
}
/*
* This is needed, because copy_page and memcpy are not usable for copying
* task structs.
*/
static inline void do_copy_page(long *dst, long *src)
{
int n;
for (n = PAGE_SIZE / sizeof(long); n; n--)
*dst++ = *src++;
}
/**
* safe_copy_page - Copy a page in a safe way.
*
* Check if the page we are going to copy is marked as present in the kernel
* page tables. This always is the case if CONFIG_DEBUG_PAGEALLOC or
* CONFIG_ARCH_HAS_SET_DIRECT_MAP is not set. In that case kernel_page_present()
* always returns 'true'.
*/
static void safe_copy_page(void *dst, struct page *s_page)
{
if (kernel_page_present(s_page)) {
do_copy_page(dst, page_address(s_page));
} else {
kernel_map_pages(s_page, 1, 1);
do_copy_page(dst, page_address(s_page));
kernel_map_pages(s_page, 1, 0);
}
}
#ifdef CONFIG_HIGHMEM
static inline struct page *page_is_saveable(struct zone *zone, unsigned long pfn)
{
return is_highmem(zone) ?
saveable_highmem_page(zone, pfn) : saveable_page(zone, pfn);
}
static void copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
{
struct page *s_page, *d_page;
void *src, *dst;
s_page = pfn_to_page(src_pfn);
d_page = pfn_to_page(dst_pfn);
if (PageHighMem(s_page)) {
src = kmap_atomic(s_page);
dst = kmap_atomic(d_page);
do_copy_page(dst, src);
kunmap_atomic(dst);
kunmap_atomic(src);
} else {
if (PageHighMem(d_page)) {
/*
* The page pointed to by src may contain some kernel
* data modified by kmap_atomic()
*/
safe_copy_page(buffer, s_page);
dst = kmap_atomic(d_page);
copy_page(dst, buffer);
kunmap_atomic(dst);
} else {
safe_copy_page(page_address(d_page), s_page);
}
}
}
#else
#define page_is_saveable(zone, pfn) saveable_page(zone, pfn)
static inline void copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
{
safe_copy_page(page_address(pfn_to_page(dst_pfn)),
pfn_to_page(src_pfn));
}
#endif /* CONFIG_HIGHMEM */
static void copy_data_pages(struct memory_bitmap *copy_bm,
struct memory_bitmap *orig_bm)
{
struct zone *zone;
unsigned long pfn;
for_each_populated_zone(zone) {
unsigned long max_zone_pfn;
mark_free_pages(zone);
max_zone_pfn = zone_end_pfn(zone);
for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
if (page_is_saveable(zone, pfn))
memory_bm_set_bit(orig_bm, pfn);
}
memory_bm_position_reset(orig_bm);
memory_bm_position_reset(copy_bm);
for(;;) {
pfn = memory_bm_next_pfn(orig_bm);
if (unlikely(pfn == BM_END_OF_MAP))
break;
copy_data_page(memory_bm_next_pfn(copy_bm), pfn);
}
}
/* Total number of image pages */
static unsigned int nr_copy_pages;
/* Number of pages needed for saving the original pfns of the image pages */
static unsigned int nr_meta_pages;
/*
* Numbers of normal and highmem page frames allocated for hibernation image
* before suspending devices.
*/
static unsigned int alloc_normal, alloc_highmem;
/*
* Memory bitmap used for marking saveable pages (during hibernation) or
* hibernation image pages (during restore)
*/
static struct memory_bitmap orig_bm;
/*
* Memory bitmap used during hibernation for marking allocated page frames that
* will contain copies of saveable pages. During restore it is initially used
* for marking hibernation image pages, but then the set bits from it are
* duplicated in @orig_bm and it is released. On highmem systems it is next
* used for marking "safe" highmem pages, but it has to be reinitialized for
* this purpose.
*/
static struct memory_bitmap copy_bm;
/**
* swsusp_free - Free pages allocated for hibernation image.
*
* Image pages are alocated before snapshot creation, so they need to be
* released after resume.
*/
void swsusp_free(void)
{
unsigned long fb_pfn, fr_pfn;
if (!forbidden_pages_map || !free_pages_map)
goto out;
memory_bm_position_reset(forbidden_pages_map);
memory_bm_position_reset(free_pages_map);
loop:
fr_pfn = memory_bm_next_pfn(free_pages_map);
fb_pfn = memory_bm_next_pfn(forbidden_pages_map);
/*
* Find the next bit set in both bitmaps. This is guaranteed to
* terminate when fb_pfn == fr_pfn == BM_END_OF_MAP.
*/
do {
if (fb_pfn < fr_pfn)
fb_pfn = memory_bm_next_pfn(forbidden_pages_map);
if (fr_pfn < fb_pfn)
fr_pfn = memory_bm_next_pfn(free_pages_map);
} while (fb_pfn != fr_pfn);
if (fr_pfn != BM_END_OF_MAP && pfn_valid(fr_pfn)) {
struct page *page = pfn_to_page(fr_pfn);
memory_bm_clear_current(forbidden_pages_map);
memory_bm_clear_current(free_pages_map);
hibernate_restore_unprotect_page(page_address(page));
__free_page(page);
goto loop;
}
out:
nr_copy_pages = 0;
nr_meta_pages = 0;
restore_pblist = NULL;
buffer = NULL;
alloc_normal = 0;
alloc_highmem = 0;
hibernate_restore_protection_end();
}
/* Helper functions used for the shrinking of memory. */
#define GFP_IMAGE (GFP_KERNEL | __GFP_NOWARN)
/**
* preallocate_image_pages - Allocate a number of pages for hibernation image.
* @nr_pages: Number of page frames to allocate.
* @mask: GFP flags to use for the allocation.
*
* Return value: Number of page frames actually allocated
*/
static unsigned long preallocate_image_pages(unsigned long nr_pages, gfp_t mask)
{
unsigned long nr_alloc = 0;
while (nr_pages > 0) {
struct page *page;
page = alloc_image_page(mask);
if (!page)
break;
memory_bm_set_bit(&copy_bm, page_to_pfn(page));
if (PageHighMem(page))
alloc_highmem++;
else
alloc_normal++;
nr_pages--;
nr_alloc++;
}
return nr_alloc;
}
static unsigned long preallocate_image_memory(unsigned long nr_pages,
unsigned long avail_normal)
{
unsigned long alloc;
if (avail_normal <= alloc_normal)
return 0;
alloc = avail_normal - alloc_normal;
if (nr_pages < alloc)
alloc = nr_pages;
return preallocate_image_pages(alloc, GFP_IMAGE);
}
#ifdef CONFIG_HIGHMEM
static unsigned long preallocate_image_highmem(unsigned long nr_pages)
{
return preallocate_image_pages(nr_pages, GFP_IMAGE | __GFP_HIGHMEM);
}
/**
* __fraction - Compute (an approximation of) x * (multiplier / base).
*/
static unsigned long __fraction(u64 x, u64 multiplier, u64 base)
{
return div64_u64(x * multiplier, base);
}
static unsigned long preallocate_highmem_fraction(unsigned long nr_pages,
unsigned long highmem,
unsigned long total)
{
unsigned long alloc = __fraction(nr_pages, highmem, total);
return preallocate_image_pages(alloc, GFP_IMAGE | __GFP_HIGHMEM);
}
#else /* CONFIG_HIGHMEM */
static inline unsigned long preallocate_image_highmem(unsigned long nr_pages)
{
return 0;
}
static inline unsigned long preallocate_highmem_fraction(unsigned long nr_pages,
unsigned long highmem,
unsigned long total)
{
return 0;
}
#endif /* CONFIG_HIGHMEM */
/**
* free_unnecessary_pages - Release preallocated pages not needed for the image.
*/
static unsigned long free_unnecessary_pages(void)
{
unsigned long save, to_free_normal, to_free_highmem, free;
save = count_data_pages();
if (alloc_normal >= save) {
to_free_normal = alloc_normal - save;
save = 0;
} else {
to_free_normal = 0;
save -= alloc_normal;
}
save += count_highmem_pages();
if (alloc_highmem >= save) {
to_free_highmem = alloc_highmem - save;
} else {
to_free_highmem = 0;
save -= alloc_highmem;
if (to_free_normal > save)
to_free_normal -= save;
else
to_free_normal = 0;
}
free = to_free_normal + to_free_highmem;
memory_bm_position_reset(&copy_bm);
while (to_free_normal > 0 || to_free_highmem > 0) {
unsigned long pfn = memory_bm_next_pfn(&copy_bm);
struct page *page = pfn_to_page(pfn);
if (PageHighMem(page)) {
if (!to_free_highmem)
continue;
to_free_highmem--;
alloc_highmem--;
} else {
if (!to_free_normal)
continue;
to_free_normal--;
alloc_normal--;
}
memory_bm_clear_bit(&copy_bm, pfn);
swsusp_unset_page_forbidden(page);
swsusp_unset_page_free(page);
__free_page(page);
}
return free;
}
/**
* minimum_image_size - Estimate the minimum acceptable size of an image.
* @saveable: Number of saveable pages in the system.
*
* We want to avoid attempting to free too much memory too hard, so estimate the
* minimum acceptable size of a hibernation image to use as the lower limit for
* preallocating memory.
*
* We assume that the minimum image size should be proportional to
*
* [number of saveable pages] - [number of pages that can be freed in theory]
*
* where the second term is the sum of (1) reclaimable slab pages, (2) active
* and (3) inactive anonymous pages, (4) active and (5) inactive file pages.
*/
static unsigned long minimum_image_size(unsigned long saveable)
{
unsigned long size;
size = global_node_page_state_pages(NR_SLAB_RECLAIMABLE_B)
+ global_node_page_state(NR_ACTIVE_ANON)
+ global_node_page_state(NR_INACTIVE_ANON)
+ global_node_page_state(NR_ACTIVE_FILE)
+ global_node_page_state(NR_INACTIVE_FILE);
return saveable <= size ? 0 : saveable - size;
}
/**
* hibernate_preallocate_memory - Preallocate memory for hibernation image.
*
* To create a hibernation image it is necessary to make a copy of every page
* frame in use. We also need a number of page frames to be free during
* hibernation for allocations made while saving the image and for device
* drivers, in case they need to allocate memory from their hibernation
* callbacks (these two numbers are given by PAGES_FOR_IO (which is a rough
* estimate) and reserved_size divided by PAGE_SIZE (which is tunable through
* /sys/power/reserved_size, respectively). To make this happen, we compute the
* total number of available page frames and allocate at least
*
* ([page frames total] - PAGES_FOR_IO - [metadata pages]) / 2
* - 2 * DIV_ROUND_UP(reserved_size, PAGE_SIZE)
*
* of them, which corresponds to the maximum size of a hibernation image.
*
* If image_size is set below the number following from the above formula,
* the preallocation of memory is continued until the total number of saveable
* pages in the system is below the requested image size or the minimum
* acceptable image size returned by minimum_image_size(), whichever is greater.
*/
int hibernate_preallocate_memory(void)
{
struct zone *zone;
unsigned long saveable, size, max_size, count, highmem, pages = 0;
unsigned long alloc, save_highmem, pages_highmem, avail_normal;
ktime_t start, stop;
int error;
pr_info("Preallocating image memory\n");
start = ktime_get();
error = memory_bm_create(&orig_bm, GFP_IMAGE, PG_ANY);
if (error) {
pr_err("Cannot allocate original bitmap\n");
goto err_out;
}
error = memory_bm_create(&copy_bm, GFP_IMAGE, PG_ANY);
if (error) {
pr_err("Cannot allocate copy bitmap\n");
goto err_out;
}
alloc_normal = 0;
alloc_highmem = 0;
/* Count the number of saveable data pages. */
save_highmem = count_highmem_pages();
saveable = count_data_pages();
/*
* Compute the total number of page frames we can use (count) and the
* number of pages needed for image metadata (size).
*/
count = saveable;
saveable += save_highmem;
highmem = save_highmem;
size = 0;
for_each_populated_zone(zone) {
size += snapshot_additional_pages(zone);
if (is_highmem(zone))
highmem += zone_page_state(zone, NR_FREE_PAGES);
else
count += zone_page_state(zone, NR_FREE_PAGES);
}
avail_normal = count;
count += highmem;
count -= totalreserve_pages;
/* Compute the maximum number of saveable pages to leave in memory. */
max_size = (count - (size + PAGES_FOR_IO)) / 2
- 2 * DIV_ROUND_UP(reserved_size, PAGE_SIZE);
/* Compute the desired number of image pages specified by image_size. */
size = DIV_ROUND_UP(image_size, PAGE_SIZE);
if (size > max_size)
size = max_size;
/*
* If the desired number of image pages is at least as large as the
* current number of saveable pages in memory, allocate page frames for
* the image and we're done.
*/
if (size >= saveable) {
pages = preallocate_image_highmem(save_highmem);
pages += preallocate_image_memory(saveable - pages, avail_normal);
goto out;
}
/* Estimate the minimum size of the image. */
pages = minimum_image_size(saveable);
/*
* To avoid excessive pressure on the normal zone, leave room in it to
* accommodate an image of the minimum size (unless it's already too
* small, in which case don't preallocate pages from it at all).
*/
if (avail_normal > pages)
avail_normal -= pages;
else
avail_normal = 0;
if (size < pages)
size = min_t(unsigned long, pages, max_size);
/*
* Let the memory management subsystem know that we're going to need a
* large number of page frames to allocate and make it free some memory.
* NOTE: If this is not done, performance will be hurt badly in some
* test cases.
*/
shrink_all_memory(saveable - size);
/*
* The number of saveable pages in memory was too high, so apply some
* pressure to decrease it. First, make room for the largest possible
* image and fail if that doesn't work. Next, try to decrease the size
* of the image as much as indicated by 'size' using allocations from
* highmem and non-highmem zones separately.
*/
pages_highmem = preallocate_image_highmem(highmem / 2);
alloc = count - max_size;
if (alloc > pages_highmem)
alloc -= pages_highmem;
else
alloc = 0;
pages = preallocate_image_memory(alloc, avail_normal);
if (pages < alloc) {
/* We have exhausted non-highmem pages, try highmem. */
alloc -= pages;
pages += pages_highmem;
pages_highmem = preallocate_image_highmem(alloc);
if (pages_highmem < alloc) {
pr_err("Image allocation is %lu pages short\n",
alloc - pages_highmem);
goto err_out;
}
pages += pages_highmem;
/*
* size is the desired number of saveable pages to leave in
* memory, so try to preallocate (all memory - size) pages.
*/
alloc = (count - pages) - size;
pages += preallocate_image_highmem(alloc);
} else {
/*
* There are approximately max_size saveable pages at this point
* and we want to reduce this number down to size.
*/
alloc = max_size - size;
size = preallocate_highmem_fraction(alloc, highmem, count);
pages_highmem += size;
alloc -= size;
size = preallocate_image_memory(alloc, avail_normal);
pages_highmem += preallocate_image_highmem(alloc - size);
pages += pages_highmem + size;
}
/*
* We only need as many page frames for the image as there are saveable
* pages in memory, but we have allocated more. Release the excessive
* ones now.
*/
pages -= free_unnecessary_pages();
out:
stop = ktime_get();
pr_info("Allocated %lu pages for snapshot\n", pages);
swsusp_show_speed(start, stop, pages, "Allocated");
return 0;
err_out:
swsusp_free();
return -ENOMEM;
}
#ifdef CONFIG_HIGHMEM
/**
* count_pages_for_highmem - Count non-highmem pages needed for copying highmem.
*
* Compute the number of non-highmem pages that will be necessary for creating
* copies of highmem pages.
*/
static unsigned int count_pages_for_highmem(unsigned int nr_highmem)
{
unsigned int free_highmem = count_free_highmem_pages() + alloc_highmem;
if (free_highmem >= nr_highmem)
nr_highmem = 0;
else
nr_highmem -= free_highmem;
return nr_highmem;
}
#else
static unsigned int count_pages_for_highmem(unsigned int nr_highmem) { return 0; }
#endif /* CONFIG_HIGHMEM */
/**
* enough_free_mem - Check if there is enough free memory for the image.
*/
static int enough_free_mem(unsigned int nr_pages, unsigned int nr_highmem)
{
struct zone *zone;
unsigned int free = alloc_normal;
for_each_populated_zone(zone)
if (!is_highmem(zone))
free += zone_page_state(zone, NR_FREE_PAGES);
nr_pages += count_pages_for_highmem(nr_highmem);
pr_debug("Normal pages needed: %u + %u, available pages: %u\n",
nr_pages, PAGES_FOR_IO, free);
return free > nr_pages + PAGES_FOR_IO;
}
#ifdef CONFIG_HIGHMEM
/**
* get_highmem_buffer - Allocate a buffer for highmem pages.
*
* If there are some highmem pages in the hibernation image, we may need a
* buffer to copy them and/or load their data.
*/
static inline int get_highmem_buffer(int safe_needed)
{
buffer = get_image_page(GFP_ATOMIC, safe_needed);
return buffer ? 0 : -ENOMEM;
}
/**
* alloc_highmem_image_pages - Allocate some highmem pages for the image.
*
* Try to allocate as many pages as needed, but if the number of free highmem
* pages is less than that, allocate them all.
*/
static inline unsigned int alloc_highmem_pages(struct memory_bitmap *bm,
unsigned int nr_highmem)
{
unsigned int to_alloc = count_free_highmem_pages();
if (to_alloc > nr_highmem)
to_alloc = nr_highmem;
nr_highmem -= to_alloc;
while (to_alloc-- > 0) {
struct page *page;
page = alloc_image_page(__GFP_HIGHMEM|__GFP_KSWAPD_RECLAIM);
memory_bm_set_bit(bm, page_to_pfn(page));
}
return nr_highmem;
}
#else
static inline int get_highmem_buffer(int safe_needed) { return 0; }
static inline unsigned int alloc_highmem_pages(struct memory_bitmap *bm,
unsigned int n) { return 0; }
#endif /* CONFIG_HIGHMEM */
/**
* swsusp_alloc - Allocate memory for hibernation image.
*
* We first try to allocate as many highmem pages as there are
* saveable highmem pages in the system. If that fails, we allocate
* non-highmem pages for the copies of the remaining highmem ones.
*
* In this approach it is likely that the copies of highmem pages will
* also be located in the high memory, because of the way in which
* copy_data_pages() works.
*/
static int swsusp_alloc(struct memory_bitmap *copy_bm,
unsigned int nr_pages, unsigned int nr_highmem)
{
if (nr_highmem > 0) {
if (get_highmem_buffer(PG_ANY))
goto err_out;
if (nr_highmem > alloc_highmem) {
nr_highmem -= alloc_highmem;
nr_pages += alloc_highmem_pages(copy_bm, nr_highmem);
}
}
if (nr_pages > alloc_normal) {
nr_pages -= alloc_normal;
while (nr_pages-- > 0) {
struct page *page;
page = alloc_image_page(GFP_ATOMIC);
if (!page)
goto err_out;
memory_bm_set_bit(copy_bm, page_to_pfn(page));
}
}
return 0;
err_out:
swsusp_free();
return -ENOMEM;
}
asmlinkage __visible int swsusp_save(void)
{
unsigned int nr_pages, nr_highmem;
pr_info("Creating image:\n");
drain_local_pages(NULL);
nr_pages = count_data_pages();
nr_highmem = count_highmem_pages();
pr_info("Need to copy %u pages\n", nr_pages + nr_highmem);
if (!enough_free_mem(nr_pages, nr_highmem)) {
pr_err("Not enough free memory\n");
return -ENOMEM;
}
if (swsusp_alloc(&copy_bm, nr_pages, nr_highmem)) {
pr_err("Memory allocation failed\n");
return -ENOMEM;
}
/*
* During allocating of suspend pagedir, new cold pages may appear.
* Kill them.
*/
drain_local_pages(NULL);
copy_data_pages(&copy_bm, &orig_bm);
/*
* End of critical section. From now on, we can write to memory,
* but we should not touch disk. This specially means we must _not_
* touch swap space! Except we must write out our image of course.
*/
nr_pages += nr_highmem;
nr_copy_pages = nr_pages;
nr_meta_pages = DIV_ROUND_UP(nr_pages * sizeof(long), PAGE_SIZE);
pr_info("Image created (%d pages copied)\n", nr_pages);
return 0;
}
#ifndef CONFIG_ARCH_HIBERNATION_HEADER
static int init_header_complete(struct swsusp_info *info)
{
memcpy(&info->uts, init_utsname(), sizeof(struct new_utsname));
info->version_code = LINUX_VERSION_CODE;
return 0;
}
static const char *check_image_kernel(struct swsusp_info *info)
{
if (info->version_code != LINUX_VERSION_CODE)
return "kernel version";
if (strcmp(info->uts.sysname,init_utsname()->sysname))
return "system type";
if (strcmp(info->uts.release,init_utsname()->release))
return "kernel release";
if (strcmp(info->uts.version,init_utsname()->version))
return "version";
if (strcmp(info->uts.machine,init_utsname()->machine))
return "machine";
return NULL;
}
#endif /* CONFIG_ARCH_HIBERNATION_HEADER */
unsigned long snapshot_get_image_size(void)
{
return nr_copy_pages + nr_meta_pages + 1;
}
static int init_header(struct swsusp_info *info)
{
memset(info, 0, sizeof(struct swsusp_info));
info->num_physpages = get_num_physpages();
info->image_pages = nr_copy_pages;
info->pages = snapshot_get_image_size();
info->size = info->pages;
info->size <<= PAGE_SHIFT;
return init_header_complete(info);
}
/**
* pack_pfns - Prepare PFNs for saving.
* @bm: Memory bitmap.
* @buf: Memory buffer to store the PFNs in.
*
* PFNs corresponding to set bits in @bm are stored in the area of memory
* pointed to by @buf (1 page at a time).
*/
static inline void pack_pfns(unsigned long *buf, struct memory_bitmap *bm)
{
int j;
for (j = 0; j < PAGE_SIZE / sizeof(long); j++) {
buf[j] = memory_bm_next_pfn(bm);
if (unlikely(buf[j] == BM_END_OF_MAP))
break;
}
}
/**
* snapshot_read_next - Get the address to read the next image page from.
* @handle: Snapshot handle to be used for the reading.
*
* On the first call, @handle should point to a zeroed snapshot_handle
* structure. The structure gets populated then and a pointer to it should be
* passed to this function every next time.
*
* On success, the function returns a positive number. Then, the caller
* is allowed to read up to the returned number of bytes from the memory
* location computed by the data_of() macro.
*
* The function returns 0 to indicate the end of the data stream condition,
* and negative numbers are returned on errors. If that happens, the structure
* pointed to by @handle is not updated and should not be used any more.
*/
int snapshot_read_next(struct snapshot_handle *handle)
{
if (handle->cur > nr_meta_pages + nr_copy_pages)
return 0;
if (!buffer) {
/* This makes the buffer be freed by swsusp_free() */
buffer = get_image_page(GFP_ATOMIC, PG_ANY);
if (!buffer)
return -ENOMEM;
}
if (!handle->cur) {
int error;
error = init_header((struct swsusp_info *)buffer);
if (error)
return error;
handle->buffer = buffer;
memory_bm_position_reset(&orig_bm);
memory_bm_position_reset(&copy_bm);
} else if (handle->cur <= nr_meta_pages) {
clear_page(buffer);
pack_pfns(buffer, &orig_bm);
} else {
struct page *page;
page = pfn_to_page(memory_bm_next_pfn(&copy_bm));
if (PageHighMem(page)) {
/*
* Highmem pages are copied to the buffer,
* because we can't return with a kmapped
* highmem page (we may not be called again).
*/
void *kaddr;
kaddr = kmap_atomic(page);
copy_page(buffer, kaddr);
kunmap_atomic(kaddr);
handle->buffer = buffer;
} else {
handle->buffer = page_address(page);
}
}
handle->cur++;
return PAGE_SIZE;
}
static void duplicate_memory_bitmap(struct memory_bitmap *dst,
struct memory_bitmap *src)
{
unsigned long pfn;
memory_bm_position_reset(src);
pfn = memory_bm_next_pfn(src);
while (pfn != BM_END_OF_MAP) {
memory_bm_set_bit(dst, pfn);
pfn = memory_bm_next_pfn(src);
}
}
/**
* mark_unsafe_pages - Mark pages that were used before hibernation.
*
* Mark the pages that cannot be used for storing the image during restoration,
* because they conflict with the pages that had been used before hibernation.
*/
static void mark_unsafe_pages(struct memory_bitmap *bm)
{
unsigned long pfn;
/* Clear the "free"/"unsafe" bit for all PFNs */
memory_bm_position_reset(free_pages_map);
pfn = memory_bm_next_pfn(free_pages_map);
while (pfn != BM_END_OF_MAP) {
memory_bm_clear_current(free_pages_map);
pfn = memory_bm_next_pfn(free_pages_map);
}
/* Mark pages that correspond to the "original" PFNs as "unsafe" */
duplicate_memory_bitmap(free_pages_map, bm);
allocated_unsafe_pages = 0;
}
static int check_header(struct swsusp_info *info)
{
const char *reason;
reason = check_image_kernel(info);
if (!reason && info->num_physpages != get_num_physpages())
reason = "memory size";
if (reason) {
pr_err("Image mismatch: %s\n", reason);
return -EPERM;
}
return 0;
}
/**
* load header - Check the image header and copy the data from it.
*/
static int load_header(struct swsusp_info *info)
{
int error;
restore_pblist = NULL;
error = check_header(info);
if (!error) {
nr_copy_pages = info->image_pages;
nr_meta_pages = info->pages - info->image_pages - 1;
}
return error;
}
/**
* unpack_orig_pfns - Set bits corresponding to given PFNs in a memory bitmap.
* @bm: Memory bitmap.
* @buf: Area of memory containing the PFNs.
*
* For each element of the array pointed to by @buf (1 page at a time), set the
* corresponding bit in @bm.
*/
static int unpack_orig_pfns(unsigned long *buf, struct memory_bitmap *bm)
{
int j;
for (j = 0; j < PAGE_SIZE / sizeof(long); j++) {
if (unlikely(buf[j] == BM_END_OF_MAP))
break;
if (pfn_valid(buf[j]) && memory_bm_pfn_present(bm, buf[j]))
memory_bm_set_bit(bm, buf[j]);
else
return -EFAULT;
}
return 0;
}
#ifdef CONFIG_HIGHMEM
/*
* struct highmem_pbe is used for creating the list of highmem pages that
* should be restored atomically during the resume from disk, because the page
* frames they have occupied before the suspend are in use.
*/
struct highmem_pbe {
struct page *copy_page; /* data is here now */
struct page *orig_page; /* data was here before the suspend */
struct highmem_pbe *next;
};
/*
* List of highmem PBEs needed for restoring the highmem pages that were
* allocated before the suspend and included in the suspend image, but have
* also been allocated by the "resume" kernel, so their contents cannot be
* written directly to their "original" page frames.
*/
static struct highmem_pbe *highmem_pblist;
/**
* count_highmem_image_pages - Compute the number of highmem pages in the image.
* @bm: Memory bitmap.
*
* The bits in @bm that correspond to image pages are assumed to be set.
*/
static unsigned int count_highmem_image_pages(struct memory_bitmap *bm)
{
unsigned long pfn;
unsigned int cnt = 0;
memory_bm_position_reset(bm);
pfn = memory_bm_next_pfn(bm);
while (pfn != BM_END_OF_MAP) {
if (PageHighMem(pfn_to_page(pfn)))
cnt++;
pfn = memory_bm_next_pfn(bm);
}
return cnt;
}
static unsigned int safe_highmem_pages;
static struct memory_bitmap *safe_highmem_bm;
/**
* prepare_highmem_image - Allocate memory for loading highmem data from image.
* @bm: Pointer to an uninitialized memory bitmap structure.
* @nr_highmem_p: Pointer to the number of highmem image pages.
*
* Try to allocate as many highmem pages as there are highmem image pages
* (@nr_highmem_p points to the variable containing the number of highmem image
* pages). The pages that are "safe" (ie. will not be overwritten when the
* hibernation image is restored entirely) have the corresponding bits set in
* @bm (it must be unitialized).
*
* NOTE: This function should not be called if there are no highmem image pages.
*/
static int prepare_highmem_image(struct memory_bitmap *bm,
unsigned int *nr_highmem_p)
{
unsigned int to_alloc;
if (memory_bm_create(bm, GFP_ATOMIC, PG_SAFE))
return -ENOMEM;
if (get_highmem_buffer(PG_SAFE))
return -ENOMEM;
to_alloc = count_free_highmem_pages();
if (to_alloc > *nr_highmem_p)
to_alloc = *nr_highmem_p;
else
*nr_highmem_p = to_alloc;
safe_highmem_pages = 0;
while (to_alloc-- > 0) {
struct page *page;
page = alloc_page(__GFP_HIGHMEM);
if (!swsusp_page_is_free(page)) {
/* The page is "safe", set its bit the bitmap */
memory_bm_set_bit(bm, page_to_pfn(page));
safe_highmem_pages++;
}
/* Mark the page as allocated */
swsusp_set_page_forbidden(page);
swsusp_set_page_free(page);
}
memory_bm_position_reset(bm);
safe_highmem_bm = bm;
return 0;
}
static struct page *last_highmem_page;
/**
* get_highmem_page_buffer - Prepare a buffer to store a highmem image page.
*
* For a given highmem image page get a buffer that suspend_write_next() should
* return to its caller to write to.
*
* If the page is to be saved to its "original" page frame or a copy of
* the page is to be made in the highmem, @buffer is returned. Otherwise,
* the copy of the page is to be made in normal memory, so the address of
* the copy is returned.
*
* If @buffer is returned, the caller of suspend_write_next() will write
* the page's contents to @buffer, so they will have to be copied to the
* right location on the next call to suspend_write_next() and it is done
* with the help of copy_last_highmem_page(). For this purpose, if
* @buffer is returned, @last_highmem_page is set to the page to which
* the data will have to be copied from @buffer.
*/
static void *get_highmem_page_buffer(struct page *page,
struct chain_allocator *ca)
{
struct highmem_pbe *pbe;
void *kaddr;
if (swsusp_page_is_forbidden(page) && swsusp_page_is_free(page)) {
/*
* We have allocated the "original" page frame and we can
* use it directly to store the loaded page.
*/
last_highmem_page = page;
return buffer;
}
/*
* The "original" page frame has not been allocated and we have to
* use a "safe" page frame to store the loaded page.
*/
pbe = chain_alloc(ca, sizeof(struct highmem_pbe));
if (!pbe) {
swsusp_free();
return ERR_PTR(-ENOMEM);
}
pbe->orig_page = page;
if (safe_highmem_pages > 0) {
struct page *tmp;
/* Copy of the page will be stored in high memory */
kaddr = buffer;
tmp = pfn_to_page(memory_bm_next_pfn(safe_highmem_bm));
safe_highmem_pages--;
last_highmem_page = tmp;
pbe->copy_page = tmp;
} else {
/* Copy of the page will be stored in normal memory */
kaddr = safe_pages_list;
safe_pages_list = safe_pages_list->next;
pbe->copy_page = virt_to_page(kaddr);
}
pbe->next = highmem_pblist;
highmem_pblist = pbe;
return kaddr;
}
/**
* copy_last_highmem_page - Copy most the most recent highmem image page.
*
* Copy the contents of a highmem image from @buffer, where the caller of
* snapshot_write_next() has stored them, to the right location represented by
* @last_highmem_page .
*/
static void copy_last_highmem_page(void)
{
if (last_highmem_page) {
void *dst;
dst = kmap_atomic(last_highmem_page);
copy_page(dst, buffer);
kunmap_atomic(dst);
last_highmem_page = NULL;
}
}
static inline int last_highmem_page_copied(void)
{
return !last_highmem_page;
}
static inline void free_highmem_data(void)
{
if (safe_highmem_bm)
memory_bm_free(safe_highmem_bm, PG_UNSAFE_CLEAR);
if (buffer)
free_image_page(buffer, PG_UNSAFE_CLEAR);
}
#else
static unsigned int count_highmem_image_pages(struct memory_bitmap *bm) { return 0; }
static inline int prepare_highmem_image(struct memory_bitmap *bm,
unsigned int *nr_highmem_p) { return 0; }
static inline void *get_highmem_page_buffer(struct page *page,
struct chain_allocator *ca)
{
return ERR_PTR(-EINVAL);
}
static inline void copy_last_highmem_page(void) {}
static inline int last_highmem_page_copied(void) { return 1; }
static inline void free_highmem_data(void) {}
#endif /* CONFIG_HIGHMEM */
#define PBES_PER_LINKED_PAGE (LINKED_PAGE_DATA_SIZE / sizeof(struct pbe))
/**
* prepare_image - Make room for loading hibernation image.
* @new_bm: Unitialized memory bitmap structure.
* @bm: Memory bitmap with unsafe pages marked.
*
* Use @bm to mark the pages that will be overwritten in the process of
* restoring the system memory state from the suspend image ("unsafe" pages)
* and allocate memory for the image.
*
* The idea is to allocate a new memory bitmap first and then allocate
* as many pages as needed for image data, but without specifying what those
* pages will be used for just yet. Instead, we mark them all as allocated and
* create a lists of "safe" pages to be used later. On systems with high
* memory a list of "safe" highmem pages is created too.
*/
static int prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm)
{
unsigned int nr_pages, nr_highmem;
struct linked_page *lp;
int error;
/* If there is no highmem, the buffer will not be necessary */
free_image_page(buffer, PG_UNSAFE_CLEAR);
buffer = NULL;
nr_highmem = count_highmem_image_pages(bm);
mark_unsafe_pages(bm);
error = memory_bm_create(new_bm, GFP_ATOMIC, PG_SAFE);
if (error)
goto Free;
duplicate_memory_bitmap(new_bm, bm);
memory_bm_free(bm, PG_UNSAFE_KEEP);
if (nr_highmem > 0) {
error = prepare_highmem_image(bm, &nr_highmem);
if (error)
goto Free;
}
/*
* Reserve some safe pages for potential later use.
*
* NOTE: This way we make sure there will be enough safe pages for the
* chain_alloc() in get_buffer(). It is a bit wasteful, but
* nr_copy_pages cannot be greater than 50% of the memory anyway.
*
* nr_copy_pages cannot be less than allocated_unsafe_pages too.
*/
nr_pages = nr_copy_pages - nr_highmem - allocated_unsafe_pages;
nr_pages = DIV_ROUND_UP(nr_pages, PBES_PER_LINKED_PAGE);
while (nr_pages > 0) {
lp = get_image_page(GFP_ATOMIC, PG_SAFE);
if (!lp) {
error = -ENOMEM;
goto Free;
}
lp->next = safe_pages_list;
safe_pages_list = lp;
nr_pages--;
}
/* Preallocate memory for the image */
nr_pages = nr_copy_pages - nr_highmem - allocated_unsafe_pages;
while (nr_pages > 0) {
lp = (struct linked_page *)get_zeroed_page(GFP_ATOMIC);
if (!lp) {
error = -ENOMEM;
goto Free;
}
if (!swsusp_page_is_free(virt_to_page(lp))) {
/* The page is "safe", add it to the list */
lp->next = safe_pages_list;
safe_pages_list = lp;
}
/* Mark the page as allocated */
swsusp_set_page_forbidden(virt_to_page(lp));
swsusp_set_page_free(virt_to_page(lp));
nr_pages--;
}
return 0;
Free:
swsusp_free();
return error;
}
/**
* get_buffer - Get the address to store the next image data page.
*
* Get the address that snapshot_write_next() should return to its caller to
* write to.
*/
static void *get_buffer(struct memory_bitmap *bm, struct chain_allocator *ca)
{
struct pbe *pbe;
struct page *page;
unsigned long pfn = memory_bm_next_pfn(bm);
if (pfn == BM_END_OF_MAP)
return ERR_PTR(-EFAULT);
page = pfn_to_page(pfn);
if (PageHighMem(page))
return get_highmem_page_buffer(page, ca);
if (swsusp_page_is_forbidden(page) && swsusp_page_is_free(page))
/*
* We have allocated the "original" page frame and we can
* use it directly to store the loaded page.
*/
return page_address(page);
/*
* The "original" page frame has not been allocated and we have to
* use a "safe" page frame to store the loaded page.
*/
pbe = chain_alloc(ca, sizeof(struct pbe));
if (!pbe) {
swsusp_free();
return ERR_PTR(-ENOMEM);
}
pbe->orig_address = page_address(page);
pbe->address = safe_pages_list;
safe_pages_list = safe_pages_list->next;
pbe->next = restore_pblist;
restore_pblist = pbe;
return pbe->address;
}
/**
* snapshot_write_next - Get the address to store the next image page.
* @handle: Snapshot handle structure to guide the writing.
*
* On the first call, @handle should point to a zeroed snapshot_handle
* structure. The structure gets populated then and a pointer to it should be
* passed to this function every next time.
*
* On success, the function returns a positive number. Then, the caller
* is allowed to write up to the returned number of bytes to the memory
* location computed by the data_of() macro.
*
* The function returns 0 to indicate the "end of file" condition. Negative
* numbers are returned on errors, in which cases the structure pointed to by
* @handle is not updated and should not be used any more.
*/
int snapshot_write_next(struct snapshot_handle *handle)
{
static struct chain_allocator ca;
int error = 0;
/* Check if we have already loaded the entire image */
if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages)
return 0;
handle->sync_read = 1;
if (!handle->cur) {
if (!buffer)
/* This makes the buffer be freed by swsusp_free() */
buffer = get_image_page(GFP_ATOMIC, PG_ANY);
if (!buffer)
return -ENOMEM;
handle->buffer = buffer;
} else if (handle->cur == 1) {
error = load_header(buffer);
if (error)
return error;
safe_pages_list = NULL;
error = memory_bm_create(&copy_bm, GFP_ATOMIC, PG_ANY);
if (error)
return error;
hibernate_restore_protection_begin();
} else if (handle->cur <= nr_meta_pages + 1) {
error = unpack_orig_pfns(buffer, &copy_bm);
if (error)
return error;
if (handle->cur == nr_meta_pages + 1) {
error = prepare_image(&orig_bm, &copy_bm);
if (error)
return error;
chain_init(&ca, GFP_ATOMIC, PG_SAFE);
memory_bm_position_reset(&orig_bm);
restore_pblist = NULL;
handle->buffer = get_buffer(&orig_bm, &ca);
handle->sync_read = 0;
if (IS_ERR(handle->buffer))
return PTR_ERR(handle->buffer);
}
} else {
copy_last_highmem_page();
hibernate_restore_protect_page(handle->buffer);
handle->buffer = get_buffer(&orig_bm, &ca);
if (IS_ERR(handle->buffer))
return PTR_ERR(handle->buffer);
if (handle->buffer != buffer)
handle->sync_read = 0;
}
handle->cur++;
return PAGE_SIZE;
}
/**
* snapshot_write_finalize - Complete the loading of a hibernation image.
*
* Must be called after the last call to snapshot_write_next() in case the last
* page in the image happens to be a highmem page and its contents should be
* stored in highmem. Additionally, it recycles bitmap memory that's not
* necessary any more.
*/
void snapshot_write_finalize(struct snapshot_handle *handle)
{
copy_last_highmem_page();
hibernate_restore_protect_page(handle->buffer);
/* Do that only if we have loaded the image entirely */
if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages) {
memory_bm_recycle(&orig_bm);
free_highmem_data();
}
}
int snapshot_image_loaded(struct snapshot_handle *handle)
{
return !(!nr_copy_pages || !last_highmem_page_copied() ||
handle->cur <= nr_meta_pages + nr_copy_pages);
}
#ifdef CONFIG_HIGHMEM
/* Assumes that @buf is ready and points to a "safe" page */
static inline void swap_two_pages_data(struct page *p1, struct page *p2,
void *buf)
{
void *kaddr1, *kaddr2;
kaddr1 = kmap_atomic(p1);
kaddr2 = kmap_atomic(p2);
copy_page(buf, kaddr1);
copy_page(kaddr1, kaddr2);
copy_page(kaddr2, buf);
kunmap_atomic(kaddr2);
kunmap_atomic(kaddr1);
}
/**
* restore_highmem - Put highmem image pages into their original locations.
*
* For each highmem page that was in use before hibernation and is included in
* the image, and also has been allocated by the "restore" kernel, swap its
* current contents with the previous (ie. "before hibernation") ones.
*
* If the restore eventually fails, we can call this function once again and
* restore the highmem state as seen by the restore kernel.
*/
int restore_highmem(void)
{
struct highmem_pbe *pbe = highmem_pblist;
void *buf;
if (!pbe)
return 0;
buf = get_image_page(GFP_ATOMIC, PG_SAFE);
if (!buf)
return -ENOMEM;
while (pbe) {
swap_two_pages_data(pbe->copy_page, pbe->orig_page, buf);
pbe = pbe->next;
}
free_image_page(buf, PG_UNSAFE_CLEAR);
return 0;
}
#endif /* CONFIG_HIGHMEM */