Merge branch 'android14-6.1' into android14-6.1-lts

Merge the recent changes in android14-6.1 into android14-6.1-lts to
catch up on abi changes and other issues fixed there already.  Changes
included in here are:

* 5a912daf87 ANDROID: OPP: fix function args mismatch for dev_pm_opp_add in pm_opp.h
* bcc435d374 ANDROID: GKI: Update KMI symbol list for ASR
* 9e167c1c27 ANDROID: GKI: Export a symbol “next_arg” for honor
* 4dcae85afd BACKPORT: netem: fix return value if duplicate enqueue fails
* f4bcd4ef0f ANDROID: 16K: Fixup padding vm_flags bits on VMA splits
* 9027204d5a ANDROID: 16K: Introduce pgsize_migration_inline.h
* 03b93dc707 FROMLIST: binder: fix BINDER_WORK_FROZEN_BINDER debug logs
* 9c6fdb6bf8 BACKPORT: FROMLIST: binder: fix freeze UAF in binder_release_work()
* 07a43515b0 FROMLIST: binder: fix OOB in binder_add_freeze_work()
* a26cde4055 FROMLIST: binder: fix node UAF in binder_add_freeze_work()
* df571cd9f1 FROMGIT: virtio_pmem: Check device status before requesting flush
* b2a0a8f709 ANDROID: GKI: update rockchip symbols sync with kernel update
* 83e7e0486e ANDROID: GKI: Update symbol list for honor
* 5c7d0d4f4a ANDROID: GKI: Update `kernel_aarch64_16k` build config to match `kernel_aarch64`
* 2cd8ac816d ANDROID: ABI: update symbol list for honor
* b5ee53c64e ANDROID: Allow vendor modules perform more operationson on sock.
* e64a80a096 ANDROID: GKI: update symbol list file for xiaomi
* 530ff6a3e6 ANDROID: GKI: add vendor hooks android_vh_page_should_be_protected() and android_vh_modify_scan_control().
* 41e1c6f937 Merge tag 'android14-6.1.99_r00' into android14-6.1
* 3b95e54867 ANDROID: Update the ABI symbol list
* b3a2458fc6 ANDROID: mm: add vh for kcompactd_cpu_online()
* 532fad0092 ANDROID: ABI: update symbol list for honor
* 145b08312d ANDROID: vendor_hooks: add hook to perform targeted memory management
* c105083ac6 ANDROID: ABI: update symbol list for honor
* eda4e9fa64 ANDROID: mm: add vendor hook in fault and read file
* 814dd5bfa8 ANDROID: Update the ABI symbol list
* 8a268cb981 ANDROID: GKI: Update symbol list for honor
* be07389110 ANDROID: Allow vendor modules perform operationson on memleak detect
* 47871c381d ANDROID: GKI: Update symbol list for honor
* c7b8f95c21 ANDROID: Allow vendor modules perform more operations on binder transaction.
* d1f3a046a6 FROMGIT: f2fs: prevent atomic file from being dirtied before commit
* 6e5b92a6a1 ANDROID: GKI: Add symbol list for exynosauto
* b18f8bbc04 ANDROID: GKI: Update symbol list for BCMSTB
* ff74052448 BACKPORT: binder_alloc: Fix sleeping function called from invalid context
* 75c9b1955b UPSTREAM: bpf: Fix overrunning reservations in ringbuf
* fdec2610bf ANDROID: gki_config: Disable CONFIG_DEBUG_STACK_USAGE
* d02968a023 ANDROID: gki_defconfig: Enable CONFIG_SERIAL_8250_BCM7271
* a752cdd96f BACKPORT: serial: 8250_bcm7271: improve bcm7271 8250 port
* 04212acc42 ANDROID: GKI: Add initial symbol list for honor
* 27310ed6b6 ANDROID: binder: fix KMI issues due to frozen notification
* 2f43c68d05 FROMGIT: binder: frozen notification binder_features flag
* eda0570485 BACKPORT: FROMGIT: binder: frozen notification
* 822682e75d ANDROID: KVM: arm64: Fix cpu type for tracing HVCs
* c7596f093d ANDROID: gki_defconfig: Enable CONFIG_RTC_HCTOSYS for x86
* d1af8906d9 ANDROID: GKI: Update symbol list for vivo
* 9eca8763c1 ANDROID: vendor_hooks: add hooks for exting task's swp_entrys
* 03a4ae5d99 ANDROID: gki_defconfig: Enable Broadcom SoCs
* ef0ea14d63 ANDROID: ABI: Update xiaomi symbol list
* eabf8327ed ANDROID: Update the ABI symbol list
* f88293625b UPSTREAM: PM: domains: Add helper functions to attach/detach multiple PM domains
* 7b1e2d9798 UPSTREAM: OPP: Fix -Wunsequenced in _of_add_opp_table_v1()
* c33dbb3b87 UPSTREAM: firmware: arm_scmi: Specify the performance level when adding an OPP
* 47933171f3 BACKPORT: firmware: arm_scmi: Simplify error path in scmi_dvfs_device_opps_add()
* b50a013d33 BACKPORT: OPP: Extend support for the opp-level beyond required-opps
* 9ba5e19e0d UPSTREAM: OPP: Extend dev_pm_opp_data with a level
* adf41f4737 BACKPORT: OPP: Add dev_pm_opp_add_dynamic() to allow more flexibility
* 9c1597d2e4 UPSTREAM: dt-bindings: power: Clarify performance capabilities of power-domains
* dda942f010 UPSTREAM: dt-bindings: firmware: arm,scmi: Extend bindings for protocol@13
* ff18572d05 UPSTREAM: dt-bindings: arm: cpus: Add a power-domain-name for a performance-domain
* 5c0092ff97 UPSTREAM: PM: domains: Allow genpd providers to manage OPP tables directly by its FW
* c638aef4e9 UPSTREAM: cpufreq: scmi: Add support to parse domain-id using #power-domain-cells
* 0ccb8d6efa UPSTREAM: cpufreq: scmi: Avoid one OF parsing in scmi_get_sharing_cpus()
* 1a6e883184 UPSTREAM: firmware: arm_scmi: Drop redundant ->device_domain_id() from perf ops
* 3aa5b5408f UPSTREAM: firmware: arm_scmi: Align perf ops to use domain-id as in-parameter
* 49da9f2745 UPSTREAM: cpufreq: scmi: Prepare to move OF parsing of domain-id to cpufreq
* 742d32f206 BACKPORT: firmware: arm_scmi: Extend perf protocol ops to get information of a domain
* b99f37e4a6 BACKPORT: firmware: arm_scmi: Extend perf protocol ops to get number of domains
* 09ab235661 ANDROID: vendor_hooks: export shrink_slab
* 8a0fa49a77 UPSTREAM: erofs: fix out-of-bound access when z_erofs_gbuf_growsize() partially fails
* 7c5c6b6397 UPSTREAM: netfilter: ipset: Fix race between namespace cleanup and gc in the list:set type
* a1895da8bd ANDROID: GKI: Add initial sunxi symbol list
* b5e374dda9 FROMLIST: usb: typec: fix up incorrectly backported "usb: typec: tcpm: unregister existing source caps before re-registration"
* 841cae8810 UPSTREAM: net: sched: sch_multiq: fix possible OOB write in multiq_tune()
* 3bb5a64ae9 ANDROID: Update the ABI symbol list
* 6cbdf0e239 ANDROID: Update the ABI symbol list
* 25641a61ba ANDROID: GKI: Update symbol list for mtk
* 82b9eb64eb FROMGIT: KVM: arm64: Ensure TLBI uses correct VMID after changing context
* 9920d2584e FROMGIT: KVM: arm64: Invalidate EL1&0 TLB entries for all VMIDs in nvhe hyp init
* 1a48a88fcb FROMGIT: BACKPORT: KVM: arm64: Don't pass a TLBI level hint when zapping table entries
* 02fcfc12fc Merge tag 'android14-6.1.93_r00' into android14-6.1
* 42515e9246 ANDROID: sched: Add android_vh_set_task_comm
* 0f23336b97 BACKPORT: UPSTREAM: sched: Move psi_account_irqtime() out of update_rq_clock_task() hotpath
* 370ea8bc2e FROMLIST: binder: fix UAF caused by offsets overwrite
* f8f9a197f4 ANDROID: binder: fix KMI-break due to proc->dmap
* a55053f3a8 UPSTREAM: binder: fix descriptor lookup for context manager
* c5f1e68340 BACKPORT: binder: use bitmap for faster descriptor lookup
* 514bdc80b9 UPSTREAM: perf/core: Fix potential NULL deref
* faf32723dc BACKPORT: scsi: ufs: core: Fix ufshcd_abort_one racing issue
* 4d735ca7bb BACKPORT: scsi: ufs: core: Fix ufshcd_clear_cmd racing issue

Change-Id: Ib03de3ba63c1e5c7fc2782fefe352aaa5d234ba1
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2024-09-27 14:07:22 +00:00
80 changed files with 3755 additions and 271 deletions

View File

@@ -120,6 +120,7 @@ filegroup(
"android/abi_gki_aarch64_qcom",
"android/abi_gki_aarch64_rockchip",
"android/abi_gki_aarch64_sony",
"android/abi_gki_aarch64_sunxi",
"android/abi_gki_aarch64_telechips",
"android/abi_gki_aarch64_tuxera",
"android/abi_gki_aarch64_type_visibility",
@@ -144,8 +145,14 @@ define_common_kernels(target_configs = {
"make_goals": _GKI_AARCH64_MAKE_GOALS,
},
"kernel_aarch64_16k": {
"kmi_symbol_list_strict_mode": False,
"kmi_symbol_list_strict_mode": True,
"module_implicit_outs": get_gki_modules_list("arm64"),
"kmi_symbol_list": "android/abi_gki_aarch64",
"rewrite_absolute_paths_in_config": True,
"kmi_symbol_list_add_only": True,
"additional_kmi_symbol_lists": [":aarch64_additional_kmi_symbol_lists"],
"protected_exports_list": "android/abi_gki_protected_exports_aarch64",
"protected_modules_list": "android/gki_aarch64_protected_modules",
"make_goals": _GKI_AARCH64_MAKE_GOALS,
},
"kernel_aarch64_debug": {

View File

@@ -296,7 +296,9 @@ properties:
power-domains property.
For PSCI based platforms, the name corresponding to the index of the PSCI
PM domain provider, must be "psci".
PM domain provider, must be "psci". For SCMI based platforms, the name
corresponding to the index of an SCMI performance domain provider, must be
"perf".
qcom,saw:
$ref: '/schemas/types.yaml#/definitions/phandle'

View File

@@ -120,8 +120,15 @@ properties:
'#clock-cells':
const: 1
required:
- '#clock-cells'
'#power-domain-cells':
const: 1
oneOf:
- required:
- '#clock-cells'
- required:
- '#power-domain-cells'
protocol@14:
type: object

View File

@@ -13,8 +13,9 @@ maintainers:
description: |+
System on chip designs are often divided into multiple PM domains that can be
used for power gating of selected IP blocks for power saving by reduced leakage
current.
used for power gating of selected IP blocks for power saving by reduced
leakage current. Moreover, in some cases the similar PM domains may also be
capable of scaling performance for a group of IP blocks.
This device tree binding can be used to bind PM domain consumer devices with
their PM domains provided by PM domain providers. A PM domain provider can be
@@ -25,7 +26,7 @@ description: |+
properties:
$nodename:
pattern: "^(power-controller|power-domain)([@-].*)?$"
pattern: "^(power-controller|power-domain|performance-domain)([@-].*)?$"
domain-idle-states:
$ref: /schemas/types.yaml#/definitions/phandle-array
@@ -47,11 +48,11 @@ properties:
items:
maxItems: 1
description:
Phandles to the OPP tables of power domains provided by a power domain
provider. If the provider provides a single power domain only or all
the power domains provided by the provider have identical OPP tables,
then this shall contain a single phandle. Refer to ../opp/opp-v2-base.yaml
for more information.
Phandles to the OPP tables of power domains that are capable of scaling
performance, provided by a power domain provider. If the provider provides
a single power domain only or all the power domains provided by the
provider have identical OPP tables, then this shall contain a single
phandle. Refer to ../opp/opp-v2-base.yaml for more information.
"#power-domain-cells":
description:

File diff suppressed because it is too large Load Diff

View File

@@ -41,3 +41,17 @@
# required by asr_drm.ko
clk_set_rate_exclusive
clk_rate_exclusive_put
# required by mercury.ko
media_device_register_entity
media_device_unregister_entity
v4l2_ctrl_get_menu
v4l2_ctrl_type_op_equal
v4l2_ctrl_type_op_init
v4l2_ctrl_type_op_log
v4l2_m2m_buf_done_and_job_finish
v4l2_m2m_last_buf
# required by jpu_heap.ko
kmem_cache_size
memset16

View File

@@ -355,7 +355,6 @@
nr_cpu_ids
ns_capable
of_address_to_resource
of_alias_get_id
of_clk_get_by_name
of_count_phandle_with_args
of_device_get_match_data
@@ -422,7 +421,6 @@
__platform_driver_register
platform_driver_unregister
platform_get_irq
platform_get_irq_byname
platform_get_irq_byname_optional
platform_get_irq_optional
platform_get_resource
@@ -747,18 +745,6 @@
vlan_vid_add
vlan_vid_del
# required by 8250_bcm7271.ko
serial8250_do_set_termios
serial8250_do_shutdown
serial8250_do_startup
serial8250_get_port
serial8250_handle_irq
serial8250_register_8250_port
serial8250_resume_port
serial8250_suspend_port
serial8250_unregister_port
uart_write_wakeup
# required by ahci_brcm.ko
phy_calibrate
@@ -797,6 +783,7 @@
dma_sync_single_for_cpu
of_get_ethdev_address
of_platform_populate
platform_get_irq_byname
__skb_pad
synchronize_irq
@@ -1069,6 +1056,7 @@
netif_schedule_queue
netif_set_real_num_rx_queues
netif_set_real_num_tx_queues
of_alias_get_id
of_get_compatible_child
of_phy_find_device
phy_attach

View File

@@ -612,6 +612,8 @@
seq_putc
seq_puts
seq_read
serdev_device_write
serdev_device_write_wakeup
set_cpus_allowed_ptr
set_normalized_timespec64
sg_alloc_table

View File

@@ -2,6 +2,8 @@
__tracepoint_android_vh_get_page_wmark
__tracepoint_android_vh_page_add_new_anon_rmap
__tracepoint_android_vh_do_shrink_slab
__tracepoint_android_vh_should_fault_around
__traceiter_android_vh_should_fault_around
__tracepoint_android_vh_shrink_slab_bypass
__tracepoint_android_vh_mutex_init
__tracepoint_android_vh_file_is_tiny_bypass
@@ -14,6 +16,33 @@
__traceiter_android_vh_shrink_slab_bypass
__traceiter_android_vh_mutex_init
__traceiter_android_vh_file_is_tiny_bypass
__tracepoint_android_vh_do_read_fault
__tracepoint_android_vh_filemap_read
__tracepoint_android_vh_filemap_map_pages
__traceiter_android_vh_do_read_fault
__traceiter_android_vh_filemap_read
__traceiter_android_vh_filemap_map_pages
__traceiter_android_vh_modify_scan_control
__traceiter_android_vh_should_continue_reclaim
__traceiter_android_vh_tune_fault_around_bytes
binder_alloc_copy_from_buffer
kfree
__kmalloc
mod_node_page_state
page_cache_sync_ra
proc_create
profile_event_register
profile_event_unregister
drop_super
si_swapinfo
__show_mem
single_open
sock_from_file
task_cputime_adjusted
tcp_sync_mss
netdev_get_name
tcp_send_active_reset
tcp_done
udp4_lib_lookup
udp6_lib_lookup
next_arg

View File

@@ -554,6 +554,8 @@
devm_request_threaded_irq
__devm_reset_control_get
devm_reset_controller_register
devm_rproc_add
devm_rproc_alloc
devm_rtc_allocate_device
devm_rtc_nvmem_register
__devm_rtc_register_device

View File

@@ -576,6 +576,7 @@
dma_direct_free
dmaengine_unmap_put
dma_fence_add_callback
dma_fence_allocate_private_stub
dma_fence_array_create
dma_fence_array_ops
dma_fence_context_alloc
@@ -1359,6 +1360,7 @@
mbox_controller_unregister
mbox_free_channel
mbox_request_channel
mbox_request_channel_byname
mbox_send_message
memchr
memchr_inv
@@ -2307,6 +2309,7 @@
teo_cpu_get_util_threshold
teo_cpu_set_util_threshold
thermal_cdev_update
thermal_cooling_device_register
thermal_cooling_device_unregister
thermal_of_cooling_device_register
thermal_pressure
@@ -2371,6 +2374,7 @@
__traceiter_android_rvh_set_user_nice
__traceiter_android_rvh_set_user_nice_locked
__traceiter_android_rvh_tick_entry
__traceiter_android_rvh_try_to_wake_up_success
__traceiter_android_rvh_typec_tcpci_get_vbus
__traceiter_android_rvh_uclamp_eff_get
__traceiter_android_rvh_ufs_complete_init
@@ -2399,12 +2403,14 @@
__traceiter_android_vh_meminfo_proc_show
__traceiter_android_vh_mm_compaction_begin
__traceiter_android_vh_mm_compaction_end
__traceiter_android_vh_mm_kcompactd_cpu_online
__traceiter_android_vh_prio_inheritance
__traceiter_android_vh_prio_restore
__traceiter_android_vh_resume_end
__traceiter_android_vh_rmqueue
__traceiter_android_vh_scheduler_tick
__traceiter_android_vh_setscheduler_uclamp
__traceiter_android_vh_set_task_comm
__traceiter_android_vh_si_meminfo_adjust
__traceiter_android_vh_sound_usb_support_cpu_suspend
__traceiter_android_vh_sysrq_crash
@@ -2426,6 +2432,7 @@
__traceiter_android_vh_ufs_update_sysfs
__traceiter_android_vh_usb_dev_resume
__traceiter_android_vh_use_amu_fie
__traceiter_android_vh_vmscan_kswapd_done
__traceiter_clock_set_rate
__traceiter_cma_alloc_finish
__traceiter_cma_alloc_start
@@ -2444,6 +2451,7 @@
__traceiter_mmap_lock_start_locking
__traceiter_mm_vmscan_direct_reclaim_begin
__traceiter_mm_vmscan_direct_reclaim_end
__traceiter_mm_vmscan_kswapd_wake
__traceiter_pelt_cfs_tp
__traceiter_pelt_dl_tp
__traceiter_pelt_irq_tp
@@ -2501,6 +2509,7 @@
__tracepoint_android_rvh_set_user_nice
__tracepoint_android_rvh_set_user_nice_locked
__tracepoint_android_rvh_tick_entry
__tracepoint_android_rvh_try_to_wake_up_success
__tracepoint_android_rvh_typec_tcpci_get_vbus
__tracepoint_android_rvh_uclamp_eff_get
__tracepoint_android_rvh_ufs_complete_init
@@ -2529,12 +2538,14 @@
__tracepoint_android_vh_meminfo_proc_show
__tracepoint_android_vh_mm_compaction_begin
__tracepoint_android_vh_mm_compaction_end
__tracepoint_android_vh_mm_kcompactd_cpu_online
__tracepoint_android_vh_prio_inheritance
__tracepoint_android_vh_prio_restore
__tracepoint_android_vh_resume_end
__tracepoint_android_vh_rmqueue
__tracepoint_android_vh_scheduler_tick
__tracepoint_android_vh_setscheduler_uclamp
__tracepoint_android_vh_set_task_comm
__tracepoint_android_vh_si_meminfo_adjust
__tracepoint_android_vh_sound_usb_support_cpu_suspend
__tracepoint_android_vh_sysrq_crash
@@ -2556,6 +2567,7 @@
__tracepoint_android_vh_ufs_update_sysfs
__tracepoint_android_vh_usb_dev_resume
__tracepoint_android_vh_use_amu_fie
__tracepoint_android_vh_vmscan_kswapd_done
__tracepoint_clock_set_rate
__tracepoint_cma_alloc_finish
__tracepoint_cma_alloc_start
@@ -2574,6 +2586,7 @@
__tracepoint_mmap_lock_start_locking
__tracepoint_mm_vmscan_direct_reclaim_begin
__tracepoint_mm_vmscan_direct_reclaim_end
__tracepoint_mm_vmscan_kswapd_wake
__tracepoint_pelt_cfs_tp
__tracepoint_pelt_dl_tp
__tracepoint_pelt_irq_tp

View File

@@ -45,6 +45,7 @@
__arch_copy_from_user
__arch_copy_to_user
arch_freq_scale
arch_invalidate_pmem
arch_timer_read_counter
argv_free
argv_split

View File

@@ -200,6 +200,7 @@
devm_clk_bulk_get
devm_clk_bulk_get_all
devm_clk_get
devm_clk_get_enabled
devm_clk_get_optional
devm_clk_hw_register
devm_clk_register
@@ -252,6 +253,7 @@
__devm_regmap_init_i2c
__devm_regmap_init_mmio_clk
devm_regulator_bulk_get
devm_regulator_bulk_get_enable
devm_regulator_get
devm_regulator_get_optional
devm_regulator_register
@@ -1975,6 +1977,7 @@
scsi_remove_device
scsi_remove_host
scsi_rescan_device
scsi_resume_device
scsi_schedule_eh
scsi_sense_desc_find
scsi_set_sense_field_pointer

View File

@@ -0,0 +1,55 @@
[abi_symbol_list]
arp_create
clk_unregister_gate
clk_unregister_fixed_factor
dev_mc_add
dev_mc_del
dma_get_any_slave_channel
dmam_pool_create
drm_client_buffer_vmap
drm_client_framebuffer_create
drm_gem_fb_create_with_funcs
drm_property_add_enum
drm_vblank_work_init
drm_vblank_work_schedule
drm_vblank_work_cancel_sync
drm_vblank_work_flush
drm_warn_on_modeset_not_all_locked
fat_time_fat2unix
fat_time_unix2fat
gpiochip_line_is_irq
hwspin_lock_register
hwspin_lock_unregister
init_on_alloc
iio_map_array_register
iio_map_array_unregister
ioport_resource
irq_setup_alt_chip
ir_raw_event_store
ir_raw_event_handle
of_io_request_and_map
of_clk_hw_register
pinctrl_gpio_set_config
phy_queue_state_machine
phy_speed_to_str
rc_map_register
rc_map_unregister
rc_keydown
reset_control_status
skb_append
snd_dmaengine_pcm_close_release_chan
snd_dmaengine_pcm_get_chan
snd_dmaengine_pcm_open
snd_dmaengine_pcm_pointer
snd_dmaengine_pcm_trigger
spi_unregister_device
v4l2_ctrl_cluster
v4l2_g_ctrl
v4l2_i2c_new_subdev
vb2_dma_contig_set_max_seg_size
__media_entity_setup_link
__traceiter_dwc3_readl
__traceiter_dwc3_writel
__tracepoint_dwc3_readl
__tracepoint_dwc3_writel

View File

@@ -3,3 +3,6 @@
# for type visibility
ANDROID_GKI_struct_dwc3
ANDROID_GKI_struct_kernel_all_info
# symbol no longer needed
serial8250_handle_irq

View File

@@ -408,6 +408,8 @@
__traceiter_android_vh_mmap_region
__traceiter_android_vh_mutex_wait_finish
__traceiter_android_vh_mutex_wait_start
__traceiter_android_vh_oom_swapmem_gather_finish
__traceiter_android_vh_oom_swapmem_gather_init
__traceiter_android_vh_percpu_rwsem_down_read
__traceiter_android_vh_percpu_rwsem_up_write
__traceiter_android_vh_printk_hotplug
@@ -428,6 +430,9 @@
__traceiter_android_vh_shmem_swapin_folio
__traceiter_android_vh_show_resume_epoch_val
__traceiter_android_vh_show_suspend_epoch_val
__traceiter_android_vh_swapmem_gather_add_bypass
__traceiter_android_vh_swapmem_gather_finish
__traceiter_android_vh_swapmem_gather_init
__traceiter_android_vh_sysrq_crash
__traceiter_android_vh_timer_calc_index
__traceiter_android_vh_try_to_freeze_todo
@@ -513,6 +518,8 @@
__tracepoint_android_rvh_is_cpu_allowed
__tracepoint_android_rvh_migrate_queued_task
__tracepoint_android_rvh_new_task_stats
__tracepoint_android_vh_oom_swapmem_gather_finish
__tracepoint_android_vh_oom_swapmem_gather_init
__tracepoint_android_rvh_panic_unhandled
__tracepoint_android_rvh_percpu_rwsem_wait_complete
__tracepoint_android_rvh_pick_next_entity
@@ -546,6 +553,9 @@
__tracepoint_android_rvh_setscheduler
__tracepoint_android_rvh_shmem_get_folio
__tracepoint_android_rvh_show_max_freq
__tracepoint_android_vh_swapmem_gather_add_bypass
__tracepoint_android_vh_swapmem_gather_finish
__tracepoint_android_vh_swapmem_gather_init
__tracepoint_android_rvh_tick_entry
__tracepoint_android_rvh_try_to_wake_up
__tracepoint_android_rvh_try_to_wake_up_success

View File

@@ -373,6 +373,9 @@
pci_sriov_set_totalvfs
pci_num_vf
# required by shrink memory module
shrink_slab
#required by cifs.ko
add_swap_extent
asn1_ber_decoder
@@ -459,6 +462,13 @@
__fs_parse
__filemap_get_folio
#required by mem_reclaim_ctl.ko
__traceiter_android_vh_page_should_be_protected
__tracepoint_android_vh_page_should_be_protected
__traceiter_android_vh_page_referenced_check_bypass
__tracepoint_android_vh_page_referenced_check_bypass
__page_mapcount
#required by mi_async_reclaim.ko
__traceiter_android_vh_handle_trylock_failed_folio
__tracepoint_android_vh_handle_trylock_failed_folio

View File

@@ -22,6 +22,7 @@ bt_err_ratelimited
bt_info
bt_procfs_cleanup
bt_procfs_init
bt_sock_alloc
bt_sock_ioctl
bt_sock_link
bt_sock_poll

View File

@@ -402,7 +402,6 @@ CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=32
CONFIG_SERIAL_8250_RUNTIME_UARTS=0
CONFIG_SERIAL_8250_DW=y
# CONFIG_SERIAL_8250_BCM7271 is not set
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
@@ -732,6 +731,7 @@ CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_TRACE_MMIO_ACCESS=y
CONFIG_CRC_CCITT=y
CONFIG_XZ_DEC=y
CONFIG_DMA_RESTRICTED_POOL=y
CONFIG_DMA_CMA=y
CONFIG_PRINTK_TIME=y
CONFIG_PRINTK_CALLER=y
@@ -751,7 +751,6 @@ CONFIG_UBSAN_LOCAL_BOUNDS=y
CONFIG_PAGE_OWNER=y
CONFIG_PAGE_PINNER=y
CONFIG_PER_VMA_LOCK_STATS=y
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_KASAN=y
CONFIG_KASAN_HW_TAGS=y

View File

@@ -58,8 +58,8 @@ void *rb_reserve_trace_entry(struct hyp_rb_per_cpu *cpu_buffer, unsigned long le
int __pkvm_load_tracing(unsigned long pack_va, size_t pack_size);
void __pkvm_teardown_tracing(void);
int __pkvm_enable_tracing(bool enable);
int __pkvm_rb_swap_reader_page(int cpu);
int __pkvm_rb_update_footers(int cpu);
int __pkvm_rb_swap_reader_page(unsigned int cpu);
int __pkvm_rb_update_footers(unsigned int cpu);
int __pkvm_enable_event(unsigned short id, bool enable);
#define HYP_EVENT(__name, __proto, __struct, __assign, __printk) \
@@ -94,12 +94,12 @@ static inline void __pkvm_teardown_tracing(void) { }
static inline int __pkvm_enable_tracing(bool enable) { return -ENODEV; }
static inline int __pkvm_rb_swap_reader_page(int cpu)
static inline int __pkvm_rb_swap_reader_page(unsigned int cpu)
{
return -ENODEV;
}
static inline int __pkvm_rb_update_footers(int cpu)
static inline int __pkvm_rb_update_footers(unsigned int cpu)
{
return -ENODEV;
}

View File

@@ -126,7 +126,7 @@ alternative_else_nop_endif
/* Invalidate the stale TLBs from Bootloader */
tlbi alle2
tlbi vmalls12e1
tlbi alle1
dsb sy
mov_q x0, INIT_SCTLR_EL2_MMU_ON

View File

@@ -1241,14 +1241,14 @@ static void handle___pkvm_enable_tracing(struct kvm_cpu_context *host_ctxt)
static void handle___pkvm_rb_swap_reader_page(struct kvm_cpu_context *host_ctxt)
{
DECLARE_REG(int, cpu, host_ctxt, 1);
DECLARE_REG(unsigned int, cpu, host_ctxt, 1);
cpu_reg(host_ctxt, 1) = __pkvm_rb_swap_reader_page(cpu);
}
static void handle___pkvm_rb_update_footers(struct kvm_cpu_context *host_ctxt)
{
DECLARE_REG(int, cpu, host_ctxt, 1);
DECLARE_REG(unsigned int, cpu, host_ctxt, 1);
cpu_reg(host_ctxt, 1) = __pkvm_rb_update_footers(cpu);
}

View File

@@ -106,10 +106,10 @@ static void exit_vmid_context(struct tlb_inv_context *cxt)
else
__load_host_stage2();
if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {
/* Ensure write of the old VMID */
isb();
/* Ensure write of the old VMID */
isb();
if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {
if (!(cxt->sctlr & SCTLR_ELx_M)) {
write_sysreg_el1(cxt->sctlr, SYS_SCTLR);
isb();

View File

@@ -485,7 +485,7 @@ static void rb_teardown_bpage_backing(void)
hyp_buffer_pages_backing.size = 0;
}
int __pkvm_rb_update_footers(int cpu)
int __pkvm_rb_update_footers(unsigned int cpu)
{
struct hyp_rb_per_cpu *cpu_buffer;
int ret = 0;
@@ -508,9 +508,9 @@ int __pkvm_rb_update_footers(int cpu)
return ret;
}
int __pkvm_rb_swap_reader_page(int cpu)
int __pkvm_rb_swap_reader_page(unsigned int cpu)
{
struct hyp_rb_per_cpu *cpu_buffer = per_cpu_ptr(&trace_rb, cpu);
struct hyp_rb_per_cpu *cpu_buffer;
int ret = 0;
if (cpu >= hyp_nr_cpus)

View File

@@ -420,7 +420,7 @@ static int hyp_unmap_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
kvm_clear_pte(ptep);
dsb(ishst);
__tlbi_level(vae2is, __TLBI_VADDR(addr, 0), level);
__tlbi_level(vae2is, __TLBI_VADDR(addr, 0), 0);
} else {
if (end - addr < granule)
return -EINVAL;
@@ -661,10 +661,15 @@ static bool stage2_pte_needs_update(struct kvm_pgtable *pgt,
static void stage2_clear_pte(kvm_pte_t *ptep, struct kvm_s2_mmu *mmu, u64 addr,
u32 level)
{
if (!kvm_pte_valid(*ptep))
kvm_pte_t pte = *ptep;
if (!kvm_pte_valid(pte))
return;
kvm_clear_pte(ptep);
if (kvm_pte_table(pte, level))
level = 0;
kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, addr, level);
}

View File

@@ -512,7 +512,6 @@ CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_TRANSIENT=y
CONFIG_EDAC=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_HCTOSYS is not set
CONFIG_DMABUF_HEAPS=y
CONFIG_DMABUF_SYSFS_STATS=y
CONFIG_DMABUF_HEAPS_DEFERRED_FREE=y
@@ -665,7 +664,6 @@ CONFIG_UBSAN_LOCAL_BOUNDS=y
# CONFIG_UBSAN_ENUM is not set
CONFIG_PAGE_OWNER=y
CONFIG_PER_VMA_LOCK_STATS=y
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_KFENCE=y
CONFIG_KFENCE_SAMPLE_INTERVAL=500

View File

@@ -1236,6 +1236,63 @@ static struct binder_ref *binder_get_ref_olocked(struct binder_proc *proc,
return NULL;
}
/* Find the smallest unused descriptor the "slow way" */
static u32 slow_desc_lookup_olocked(struct binder_proc *proc, u32 offset)
{
struct binder_ref *ref;
struct rb_node *n;
u32 desc;
desc = offset;
for (n = rb_first(&proc->refs_by_desc); n; n = rb_next(n)) {
ref = rb_entry(n, struct binder_ref, rb_node_desc);
if (ref->data.desc > desc)
break;
desc = ref->data.desc + 1;
}
return desc;
}
/*
* Find an available reference descriptor ID. The proc->outer_lock might
* be released in the process, in which case -EAGAIN is returned and the
* @desc should be considered invalid.
*/
static int get_ref_desc_olocked(struct binder_proc *proc,
struct binder_node *node,
u32 *desc)
{
struct dbitmap *dmap = &proc_wrapper(proc)->dmap;
unsigned int nbits, offset;
unsigned long *new, bit;
/* 0 is reserved for the context manager */
offset = (node == proc->context->binder_context_mgr_node) ? 0 : 1;
if (!dbitmap_enabled(dmap)) {
*desc = slow_desc_lookup_olocked(proc, offset);
return 0;
}
if (dbitmap_acquire_next_zero_bit(dmap, offset, &bit) == 0) {
*desc = bit;
return 0;
}
/*
* The dbitmap is full and needs to grow. The proc->outer_lock
* is briefly released to allocate the new bitmap safely.
*/
nbits = dbitmap_grow_nbits(dmap);
binder_proc_unlock(proc);
new = bitmap_zalloc(nbits, GFP_KERNEL);
binder_proc_lock(proc);
dbitmap_grow(dmap, new, nbits);
return -EAGAIN;
}
/**
* binder_get_ref_for_node_olocked() - get the ref associated with given node
* @proc: binder_proc that owns the ref
@@ -1259,12 +1316,14 @@ static struct binder_ref *binder_get_ref_for_node_olocked(
struct binder_node *node,
struct binder_ref *new_ref)
{
struct binder_context *context = proc->context;
struct rb_node **p = &proc->refs_by_node.rb_node;
struct rb_node *parent = NULL;
struct binder_ref *ref;
struct rb_node *n;
struct rb_node *parent;
struct rb_node **p;
u32 desc;
retry:
p = &proc->refs_by_node.rb_node;
parent = NULL;
while (*p) {
parent = *p;
ref = rb_entry(parent, struct binder_ref, rb_node_node);
@@ -1279,6 +1338,10 @@ static struct binder_ref *binder_get_ref_for_node_olocked(
if (!new_ref)
return NULL;
/* might release the proc->outer_lock */
if (get_ref_desc_olocked(proc, node, &desc) == -EAGAIN)
goto retry;
binder_stats_created(BINDER_STAT_REF);
new_ref->data.debug_id = atomic_inc_return(&binder_last_id);
new_ref->proc = proc;
@@ -1286,14 +1349,7 @@ static struct binder_ref *binder_get_ref_for_node_olocked(
rb_link_node(&new_ref->rb_node_node, parent, p);
rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node);
new_ref->data.desc = (node == context->binder_context_mgr_node) ? 0 : 1;
for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
ref = rb_entry(n, struct binder_ref, rb_node_desc);
if (ref->data.desc > new_ref->data.desc)
break;
new_ref->data.desc = ref->data.desc + 1;
}
new_ref->data.desc = desc;
p = &proc->refs_by_desc.rb_node;
while (*p) {
parent = *p;
@@ -1323,6 +1379,7 @@ static struct binder_ref *binder_get_ref_for_node_olocked(
static void binder_cleanup_ref_olocked(struct binder_ref *ref)
{
struct dbitmap *dmap = &proc_wrapper(ref->proc)->dmap;
bool delete_node = false;
binder_debug(BINDER_DEBUG_INTERNAL_REFS,
@@ -1330,6 +1387,8 @@ static void binder_cleanup_ref_olocked(struct binder_ref *ref)
ref->proc->pid, ref->data.debug_id, ref->data.desc,
ref->node->debug_id);
if (dbitmap_enabled(dmap))
dbitmap_clear_bit(dmap, ref->data.desc);
rb_erase(&ref->rb_node_desc, &ref->proc->refs_by_desc);
rb_erase(&ref->rb_node_node, &ref->proc->refs_by_node);
@@ -1360,6 +1419,10 @@ static void binder_cleanup_ref_olocked(struct binder_ref *ref)
binder_dequeue_work(ref->proc, &ref->death->work);
binder_stats_deleted(BINDER_STAT_DEATH);
}
if (ref->freeze)
binder_dequeue_work(ref->proc, &ref->freeze->work);
binder_stats_deleted(BINDER_STAT_REF);
}
@@ -1489,9 +1552,30 @@ static void binder_free_ref(struct binder_ref *ref)
if (ref->node)
binder_free_node(ref->node);
kfree(ref->death);
kfree(ref->freeze);
kfree(ref);
}
/* shrink descriptor bitmap if needed */
static void try_shrink_dmap(struct binder_proc *proc)
{
struct dbitmap *dmap = &proc_wrapper(proc)->dmap;
unsigned long *new;
int nbits;
binder_proc_lock(proc);
nbits = dbitmap_shrink_nbits(dmap);
binder_proc_unlock(proc);
if (!nbits)
return;
new = bitmap_zalloc(nbits, GFP_KERNEL);
binder_proc_lock(proc);
dbitmap_shrink(dmap, new, nbits);
binder_proc_unlock(proc);
}
/**
* binder_update_ref_for_handle() - inc/dec the ref for given handle
* @proc: proc containing the ref
@@ -1528,8 +1612,10 @@ static int binder_update_ref_for_handle(struct binder_proc *proc,
*rdata = ref->data;
binder_proc_unlock(proc);
if (delete_ref)
if (delete_ref) {
binder_free_ref(ref);
try_shrink_dmap(proc);
}
return ret;
err_no_ref:
@@ -3564,6 +3650,7 @@ static void binder_transaction(struct binder_proc *proc,
*/
copy_size = object_offset - user_offset;
if (copy_size && (user_offset > object_offset ||
object_offset > tr->data_size ||
binder_alloc_copy_user_to_buffer(
&target_proc->alloc,
t->buffer, user_offset,
@@ -3986,6 +4073,154 @@ err_invalid_target_handle:
}
}
static int
binder_request_freeze_notification(struct binder_proc *proc,
struct binder_thread *thread,
struct binder_handle_cookie *handle_cookie)
{
struct binder_ref_freeze *freeze;
struct binder_ref *ref;
bool is_frozen;
freeze = kzalloc(sizeof(*freeze), GFP_KERNEL);
if (!freeze)
return -ENOMEM;
binder_proc_lock(proc);
ref = binder_get_ref_olocked(proc, handle_cookie->handle, false);
if (!ref) {
binder_user_error("%d:%d BC_REQUEST_FREEZE_NOTIFICATION invalid ref %d\n",
proc->pid, thread->pid, handle_cookie->handle);
binder_proc_unlock(proc);
kfree(freeze);
return -EINVAL;
}
binder_node_lock(ref->node);
if (ref->freeze || !ref->node->proc) {
binder_user_error("%d:%d invalid BC_REQUEST_FREEZE_NOTIFICATION %s\n",
proc->pid, thread->pid,
ref->freeze ? "already set" : "dead node");
binder_node_unlock(ref->node);
binder_proc_unlock(proc);
kfree(freeze);
return -EINVAL;
}
binder_inner_proc_lock(ref->node->proc);
is_frozen = ref->node->proc->is_frozen;
binder_inner_proc_unlock(ref->node->proc);
INIT_LIST_HEAD(&freeze->work.entry);
freeze->cookie = handle_cookie->cookie;
freeze->work.type = BINDER_WORK_FROZEN_BINDER;
freeze->is_frozen = is_frozen;
ref->freeze = freeze;
binder_inner_proc_lock(proc);
binder_enqueue_work_ilocked(&ref->freeze->work, &proc->todo);
binder_wakeup_proc_ilocked(proc);
binder_inner_proc_unlock(proc);
binder_node_unlock(ref->node);
binder_proc_unlock(proc);
return 0;
}
static int
binder_clear_freeze_notification(struct binder_proc *proc,
struct binder_thread *thread,
struct binder_handle_cookie *handle_cookie)
{
struct binder_ref_freeze *freeze;
struct binder_ref *ref;
binder_proc_lock(proc);
ref = binder_get_ref_olocked(proc, handle_cookie->handle, false);
if (!ref) {
binder_user_error("%d:%d BC_CLEAR_FREEZE_NOTIFICATION invalid ref %d\n",
proc->pid, thread->pid, handle_cookie->handle);
binder_proc_unlock(proc);
return -EINVAL;
}
binder_node_lock(ref->node);
if (!ref->freeze) {
binder_user_error("%d:%d BC_CLEAR_FREEZE_NOTIFICATION freeze notification not active\n",
proc->pid, thread->pid);
binder_node_unlock(ref->node);
binder_proc_unlock(proc);
return -EINVAL;
}
freeze = ref->freeze;
binder_inner_proc_lock(proc);
if (freeze->cookie != handle_cookie->cookie) {
binder_user_error("%d:%d BC_CLEAR_FREEZE_NOTIFICATION freeze notification cookie mismatch %016llx != %016llx\n",
proc->pid, thread->pid, (u64)freeze->cookie,
(u64)handle_cookie->cookie);
binder_inner_proc_unlock(proc);
binder_node_unlock(ref->node);
binder_proc_unlock(proc);
return -EINVAL;
}
ref->freeze = NULL;
/*
* Take the existing freeze object and overwrite its work type. There are three cases here:
* 1. No pending notification. In this case just add the work to the queue.
* 2. A notification was sent and is pending an ack from userspace. Once an ack arrives, we
* should resend with the new work type.
* 3. A notification is pending to be sent. Since the work is already in the queue, nothing
* needs to be done here.
*/
freeze->work.type = BINDER_WORK_CLEAR_FREEZE_NOTIFICATION;
if (list_empty(&freeze->work.entry)) {
binder_enqueue_work_ilocked(&freeze->work, &proc->todo);
binder_wakeup_proc_ilocked(proc);
} else if (freeze->sent) {
freeze->resend = true;
}
binder_inner_proc_unlock(proc);
binder_node_unlock(ref->node);
binder_proc_unlock(proc);
return 0;
}
static int
binder_freeze_notification_done(struct binder_proc *proc,
struct binder_thread *thread,
binder_uintptr_t cookie)
{
struct binder_ref_freeze *freeze = NULL;
struct binder_work *w;
binder_inner_proc_lock(proc);
list_for_each_entry(w, &proc_wrapper(proc)->delivered_freeze, entry) {
struct binder_ref_freeze *tmp_freeze =
container_of(w, struct binder_ref_freeze, work);
if (tmp_freeze->cookie == cookie) {
freeze = tmp_freeze;
break;
}
}
if (!freeze) {
binder_user_error("%d:%d BC_FREEZE_NOTIFICATION_DONE %016llx not found\n",
proc->pid, thread->pid, (u64)cookie);
binder_inner_proc_unlock(proc);
return -EINVAL;
}
binder_dequeue_work_ilocked(&freeze->work);
freeze->sent = false;
if (freeze->resend) {
freeze->resend = false;
binder_enqueue_work_ilocked(&freeze->work, &proc->todo);
binder_wakeup_proc_ilocked(proc);
}
binder_inner_proc_unlock(proc);
return 0;
}
/**
* binder_free_buf() - free the specified buffer
* @proc: binder proc that owns buffer
@@ -4480,6 +4715,44 @@ static int binder_thread_write(struct binder_proc *proc,
binder_inner_proc_unlock(proc);
} break;
case BC_REQUEST_FREEZE_NOTIFICATION: {
struct binder_handle_cookie handle_cookie;
int error;
if (copy_from_user(&handle_cookie, ptr, sizeof(handle_cookie)))
return -EFAULT;
ptr += sizeof(handle_cookie);
error = binder_request_freeze_notification(proc, thread,
&handle_cookie);
if (error)
return error;
} break;
case BC_CLEAR_FREEZE_NOTIFICATION: {
struct binder_handle_cookie handle_cookie;
int error;
if (copy_from_user(&handle_cookie, ptr, sizeof(handle_cookie)))
return -EFAULT;
ptr += sizeof(handle_cookie);
error = binder_clear_freeze_notification(proc, thread, &handle_cookie);
if (error)
return error;
} break;
case BC_FREEZE_NOTIFICATION_DONE: {
binder_uintptr_t cookie;
int error;
if (get_user(cookie, (binder_uintptr_t __user *)ptr))
return -EFAULT;
ptr += sizeof(cookie);
error = binder_freeze_notification_done(proc, thread, cookie);
if (error)
return error;
} break;
default:
pr_err("%d:%d unknown command %u\n",
proc->pid, thread->pid, cmd);
@@ -4881,6 +5154,45 @@ skip:
if (cmd == BR_DEAD_BINDER)
goto done; /* DEAD_BINDER notifications can cause transactions */
} break;
case BINDER_WORK_FROZEN_BINDER: {
struct binder_ref_freeze *freeze;
struct binder_frozen_state_info info;
memset(&info, 0, sizeof(info));
freeze = container_of(w, struct binder_ref_freeze, work);
info.is_frozen = freeze->is_frozen;
info.cookie = freeze->cookie;
freeze->sent = true;
binder_enqueue_work_ilocked(w, &proc_wrapper(proc)->delivered_freeze);
binder_inner_proc_unlock(proc);
if (put_user(BR_FROZEN_BINDER, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
if (copy_to_user(ptr, &info, sizeof(info)))
return -EFAULT;
ptr += sizeof(info);
binder_stat_br(proc, thread, BR_FROZEN_BINDER);
goto done; /* BR_FROZEN_BINDER notifications can cause transactions */
} break;
case BINDER_WORK_CLEAR_FREEZE_NOTIFICATION: {
struct binder_ref_freeze *freeze =
container_of(w, struct binder_ref_freeze, work);
binder_uintptr_t cookie = freeze->cookie;
binder_inner_proc_unlock(proc);
kfree(freeze);
if (put_user(BR_CLEAR_FREEZE_NOTIFICATION_DONE, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
if (put_user(cookie, (binder_uintptr_t __user *)ptr))
return -EFAULT;
ptr += sizeof(binder_uintptr_t);
binder_stat_br(proc, thread, BR_CLEAR_FREEZE_NOTIFICATION_DONE);
} break;
default:
binder_inner_proc_unlock(proc);
pr_err("%d:%d: bad work type %d\n",
@@ -5163,7 +5475,6 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc)
static void binder_free_proc(struct binder_proc *proc)
{
struct binder_proc_wrap *proc_wrap;
struct binder_device *device;
BUG_ON(!list_empty(&proc->todo));
@@ -5180,9 +5491,9 @@ static void binder_free_proc(struct binder_proc *proc)
put_task_struct(proc->tsk);
put_cred(proc->cred);
binder_stats_deleted(BINDER_STAT_PROC);
dbitmap_free(&proc_wrapper(proc)->dmap);
trace_android_vh_binder_free_proc(proc);
proc_wrap = binder_proc_wrap_entry(proc);
kfree(proc_wrap);
kfree(proc_wrapper(proc));
}
static void binder_free_thread(struct binder_thread *thread)
@@ -5502,6 +5813,57 @@ static bool binder_txns_pending_ilocked(struct binder_proc *proc)
return false;
}
static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen)
{
struct binder_node *prev = NULL;
struct rb_node *n;
struct binder_ref *ref;
binder_inner_proc_lock(proc);
for (n = rb_first(&proc->nodes); n; n = rb_next(n)) {
struct binder_node *node;
node = rb_entry(n, struct binder_node, rb_node);
binder_inc_node_tmpref_ilocked(node);
binder_inner_proc_unlock(proc);
if (prev)
binder_put_node(prev);
binder_node_lock(node);
hlist_for_each_entry(ref, &node->refs, node_entry) {
/*
* Need the node lock to synchronize
* with new notification requests and the
* inner lock to synchronize with queued
* freeze notifications.
*/
binder_inner_proc_lock(ref->proc);
if (!ref->freeze) {
binder_inner_proc_unlock(ref->proc);
continue;
}
ref->freeze->work.type = BINDER_WORK_FROZEN_BINDER;
if (list_empty(&ref->freeze->work.entry)) {
ref->freeze->is_frozen = is_frozen;
binder_enqueue_work_ilocked(&ref->freeze->work, &ref->proc->todo);
binder_wakeup_proc_ilocked(ref->proc);
} else {
if (ref->freeze->sent && ref->freeze->is_frozen != is_frozen)
ref->freeze->resend = true;
ref->freeze->is_frozen = is_frozen;
}
binder_inner_proc_unlock(ref->proc);
}
prev = node;
binder_node_unlock(node);
binder_inner_proc_lock(proc);
if (proc->is_dead)
break;
}
binder_inner_proc_unlock(proc);
if (prev)
binder_put_node(prev);
}
static int binder_ioctl_freeze(struct binder_freeze_info *info,
struct binder_proc *target_proc)
{
@@ -5513,6 +5875,7 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info,
target_proc->async_recv = false;
target_proc->is_frozen = false;
binder_inner_proc_unlock(target_proc);
binder_add_freeze_work(target_proc, false);
return 0;
}
@@ -5545,6 +5908,8 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info,
binder_inner_proc_lock(target_proc);
target_proc->is_frozen = false;
binder_inner_proc_unlock(target_proc);
} else {
binder_add_freeze_work(target_proc, true);
}
return ret;
@@ -5903,6 +6268,7 @@ static int binder_open(struct inode *nodp, struct file *filp)
return -ENOMEM;
proc = &proc_wrap->proc;
dbitmap_init(&proc_wrapper(proc)->dmap);
spin_lock_init(&proc->inner_lock);
spin_lock_init(&proc->outer_lock);
get_task_struct(current->group_leader);
@@ -5934,6 +6300,7 @@ static int binder_open(struct inode *nodp, struct file *filp)
binder_stats_created(BINDER_STAT_PROC);
proc->pid = current->group_leader->pid;
INIT_LIST_HEAD(&proc->delivered_death);
INIT_LIST_HEAD(&proc_wrapper(proc)->delivered_freeze);
INIT_LIST_HEAD(&proc->waiting_threads);
filp->private_data = proc;
@@ -6314,6 +6681,9 @@ static void print_binder_work_ilocked(struct seq_file *m,
case BINDER_WORK_CLEAR_DEATH_NOTIFICATION:
seq_printf(m, "%shas cleared death notification\n", prefix);
break;
case BINDER_WORK_FROZEN_BINDER:
seq_printf(m, "%shas frozen binder\n", prefix);
break;
default:
seq_printf(m, "%sunknown work: type %d\n", prefix, w->type);
break;
@@ -6520,7 +6890,7 @@ static const char * const binder_objstat_strings[] = {
"ref",
"death",
"transaction",
"transaction_complete"
"transaction_complete",
};
static void print_binder_stats(struct seq_file *m, const char *prefix,

View File

@@ -955,9 +955,9 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc)
__free_page(alloc->pages[i].page_ptr);
page_count++;
}
kfree(alloc->pages);
}
binder_alloc_unlock(alloc);
kfree(alloc->pages);
if (alloc->mm)
mmdrop(alloc->mm);
@@ -1315,4 +1315,4 @@ int binder_alloc_copy_from_buffer(struct binder_alloc *alloc,
return binder_alloc_do_buffer_copy(alloc, false, buffer, buffer_offset,
dest, bytes);
}
EXPORT_SYMBOL_GPL(binder_alloc_copy_from_buffer);

View File

@@ -14,6 +14,7 @@
#include <linux/uidgid.h>
#include <uapi/linux/android/binderfs.h>
#include "binder_alloc.h"
#include "dbitmap.h"
struct binder_context {
struct binder_node *binder_context_mgr_node;
@@ -158,6 +159,10 @@ struct binder_work {
BINDER_WORK_DEAD_BINDER,
BINDER_WORK_DEAD_BINDER_AND_CLEAR,
BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
#ifndef __GENKSYMS__
BINDER_WORK_FROZEN_BINDER,
BINDER_WORK_CLEAR_FREEZE_NOTIFICATION,
#endif
} type;
};
@@ -279,6 +284,14 @@ struct binder_ref_death {
binder_uintptr_t cookie;
};
struct binder_ref_freeze {
struct binder_work work;
binder_uintptr_t cookie;
bool is_frozen:1;
bool sent:1;
bool resend:1;
};
/**
* struct binder_ref_data - binder_ref counts and id
* @debug_id: unique ID for the ref
@@ -311,6 +324,8 @@ struct binder_ref_data {
* @node indicates the node must be freed
* @death: pointer to death notification (ref_death) if requested
* (protected by @node->lock)
* @freeze: pointer to freeze notification (ref_freeze) if requested
* (protected by @node->lock)
*
* Structure to track references from procA to target node (on procB). This
* structure is unsafe to access without holding @proc->outer_lock.
@@ -327,6 +342,7 @@ struct binder_ref {
struct binder_proc *proc;
struct binder_node *node;
struct binder_ref_death *death;
struct binder_ref_freeze *freeze;
};
/**
@@ -443,7 +459,6 @@ struct binder_proc {
bool sync_recv;
bool async_recv;
wait_queue_head_t freeze_wait;
struct list_head todo;
struct binder_stats stats;
struct list_head delivered_death;
@@ -461,27 +476,38 @@ struct binder_proc {
bool oneway_spam_detection_enabled;
};
/**
* struct binder_proc_wrap - wrapper to preserve KMI in binder_proc
* @proc: binder_proc being wrapped
* @dmap: dbitmap to manage available reference descriptors
* (protected by @proc.outer_lock)
* @lock: protects @proc->alloc fields
* @delivered_freeze: list of delivered freeze notification
* (protected by @inner_lock)
*/
struct binder_proc_wrap {
struct binder_proc proc;
struct dbitmap dmap;
spinlock_t lock;
struct list_head delivered_freeze;
};
static inline
struct binder_proc_wrap *proc_wrapper(struct binder_proc *proc)
{
return container_of(proc, struct binder_proc_wrap, proc);
}
static inline struct binder_proc *
binder_proc_entry(struct binder_alloc *alloc)
{
return container_of(alloc, struct binder_proc, alloc);
}
static inline struct binder_proc_wrap *
binder_proc_wrap_entry(struct binder_proc *proc)
{
return container_of(proc, struct binder_proc_wrap, proc);
}
static inline struct binder_proc_wrap *
binder_alloc_to_proc_wrap(struct binder_alloc *alloc)
{
return binder_proc_wrap_entry(binder_proc_entry(alloc));
return proc_wrapper(binder_proc_entry(alloc));
}
static inline void binder_alloc_lock_init(struct binder_alloc *alloc)

View File

@@ -60,6 +60,7 @@ enum binderfs_stats_mode {
struct binder_features {
bool oneway_spam_detection;
bool extended_error;
bool freeze_notification;
};
static const struct constant_table binderfs_param_stats[] = {
@@ -76,6 +77,7 @@ static const struct fs_parameter_spec binderfs_fs_parameters[] = {
static struct binder_features binder_features = {
.oneway_spam_detection = true,
.extended_error = true,
.freeze_notification = true,
};
static inline struct binderfs_info *BINDERFS_SB(const struct super_block *sb)
@@ -610,6 +612,12 @@ static int init_binder_features(struct super_block *sb)
if (IS_ERR(dentry))
return PTR_ERR(dentry);
dentry = binderfs_create_file(dir, "freeze_notification",
&binder_features_fops,
&binder_features.freeze_notification);
if (IS_ERR(dentry))
return PTR_ERR(dentry);
return 0;
}

168
drivers/android/dbitmap.h Normal file
View File

@@ -0,0 +1,168 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright 2024 Google LLC
*
* dbitmap - dynamically sized bitmap library.
*
* Used by the binder driver to optimize the allocation of the smallest
* available descriptor ID. Each bit in the bitmap represents the state
* of an ID.
*
* A dbitmap can grow or shrink as needed. This part has been designed
* considering that users might need to briefly release their locks in
* order to allocate memory for the new bitmap. These operations then,
* are verified to determine if the grow or shrink is sill valid.
*
* This library does not provide protection against concurrent access
* by itself. Binder uses the proc->outer_lock for this purpose.
*/
#ifndef _LINUX_DBITMAP_H
#define _LINUX_DBITMAP_H
#include <linux/bitmap.h>
#define NBITS_MIN BITS_PER_TYPE(unsigned long)
struct dbitmap {
unsigned int nbits;
unsigned long *map;
};
static inline int dbitmap_enabled(struct dbitmap *dmap)
{
return !!dmap->nbits;
}
static inline void dbitmap_free(struct dbitmap *dmap)
{
dmap->nbits = 0;
kfree(dmap->map);
}
/* Returns the nbits that a dbitmap can shrink to, 0 if not possible. */
static inline unsigned int dbitmap_shrink_nbits(struct dbitmap *dmap)
{
unsigned int bit;
if (dmap->nbits <= NBITS_MIN)
return 0;
/*
* Determine if the bitmap can shrink based on the position of
* its last set bit. If the bit is within the first quarter of
* the bitmap then shrinking is possible. In this case, the
* bitmap should shrink to half its current size.
*/
bit = find_last_bit(dmap->map, dmap->nbits);
if (bit < (dmap->nbits >> 2))
return dmap->nbits >> 1;
/* find_last_bit() returns dmap->nbits when no bits are set. */
if (bit == dmap->nbits)
return NBITS_MIN;
return 0;
}
/* Replace the internal bitmap with a new one of different size */
static inline void
dbitmap_replace(struct dbitmap *dmap, unsigned long *new, unsigned int nbits)
{
bitmap_copy(new, dmap->map, min(dmap->nbits, nbits));
kfree(dmap->map);
dmap->map = new;
dmap->nbits = nbits;
}
static inline void
dbitmap_shrink(struct dbitmap *dmap, unsigned long *new, unsigned int nbits)
{
if (!new)
return;
/*
* Verify that shrinking to @nbits is still possible. The @new
* bitmap might have been allocated without locks, so this call
* could now be outdated. In this case, free @new and move on.
*/
if (!dbitmap_enabled(dmap) || dbitmap_shrink_nbits(dmap) != nbits) {
kfree(new);
return;
}
dbitmap_replace(dmap, new, nbits);
}
/* Returns the nbits that a dbitmap can grow to. */
static inline unsigned int dbitmap_grow_nbits(struct dbitmap *dmap)
{
return dmap->nbits << 1;
}
static inline void
dbitmap_grow(struct dbitmap *dmap, unsigned long *new, unsigned int nbits)
{
/*
* Verify that growing to @nbits is still possible. The @new
* bitmap might have been allocated without locks, so this call
* could now be outdated. In this case, free @new and move on.
*/
if (!dbitmap_enabled(dmap) || nbits <= dmap->nbits) {
kfree(new);
return;
}
/*
* Check for ENOMEM after confirming the grow operation is still
* required. This ensures we only disable the dbitmap when it's
* necessary. Once the dbitmap is disabled, binder will fallback
* to slow_desc_lookup_olocked().
*/
if (!new) {
dbitmap_free(dmap);
return;
}
dbitmap_replace(dmap, new, nbits);
}
/*
* Finds and sets the next zero bit in the bitmap. Upon success @bit
* is populated with the index and 0 is returned. Otherwise, -ENOSPC
* is returned to indicate that a dbitmap_grow() is needed.
*/
static inline int
dbitmap_acquire_next_zero_bit(struct dbitmap *dmap, unsigned long offset,
unsigned long *bit)
{
unsigned long n;
n = find_next_zero_bit(dmap->map, dmap->nbits, offset);
if (n == dmap->nbits)
return -ENOSPC;
*bit = n;
set_bit(n, dmap->map);
return 0;
}
static inline void
dbitmap_clear_bit(struct dbitmap *dmap, unsigned long bit)
{
clear_bit(bit, dmap->map);
}
static inline int dbitmap_init(struct dbitmap *dmap)
{
dmap->map = bitmap_zalloc(NBITS_MIN, GFP_KERNEL);
if (!dmap->map) {
dmap->nbits = 0;
return -ENOMEM;
}
dmap->nbits = NBITS_MIN;
return 0;
}
#endif

View File

@@ -276,6 +276,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_set_gfp_zone_flags);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_set_readahead_gfp_mask);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alter_mutex_list_add);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mutex_unlock_slowpath);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_should_fault_around);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_wake_finish);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_tune_fault_around_bytes);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_adjust_alloc_flags);
@@ -377,6 +378,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_alloc_pages_may_oom_exit);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_vmscan_kswapd_done);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_compaction_begin);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_compaction_end);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_kcompactd_cpu_online);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_bus_iommu_probe);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rmqueue);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_resume_begin);
@@ -442,3 +444,13 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_folio_trylock_clear);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_folio_trylock_set);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_handle_trylock_failed_folio);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_hibernate_state);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_should_be_protected);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_referenced_check_bypass);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_swapmem_gather_init);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_swapmem_gather_add_bypass);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_swapmem_gather_finish);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_oom_swapmem_gather_init);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_oom_swapmem_gather_finish);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_do_read_fault);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_filemap_read);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_filemap_map_pages);

View File

@@ -167,6 +167,115 @@ struct device *dev_pm_domain_attach_by_name(struct device *dev,
}
EXPORT_SYMBOL_GPL(dev_pm_domain_attach_by_name);
/**
* dev_pm_domain_attach_list - Associate a device with its PM domains.
* @dev: The device used to lookup the PM domains for.
* @data: The data used for attaching to the PM domains.
* @list: An out-parameter with an allocated list of attached PM domains.
*
* This function helps to attach a device to its multiple PM domains. The
* caller, which is typically a driver's probe function, may provide a list of
* names for the PM domains that we should try to attach the device to, but it
* may also provide an empty list, in case the attach should be done for all of
* the available PM domains.
*
* Callers must ensure proper synchronization of this function with power
* management callbacks.
*
* Returns the number of attached PM domains or a negative error code in case of
* a failure. Note that, to detach the list of PM domains, the driver shall call
* dev_pm_domain_detach_list(), typically during the remove phase.
*/
int dev_pm_domain_attach_list(struct device *dev,
const struct dev_pm_domain_attach_data *data,
struct dev_pm_domain_list **list)
{
struct device_node *np = dev->of_node;
struct dev_pm_domain_list *pds;
struct device *pd_dev = NULL;
int ret, i, num_pds = 0;
bool by_id = true;
u32 pd_flags = data ? data->pd_flags : 0;
u32 link_flags = pd_flags & PD_FLAG_NO_DEV_LINK ? 0 :
DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME;
if (dev->pm_domain)
return -EEXIST;
/* For now this is limited to OF based platforms. */
if (!np)
return 0;
if (data && data->pd_names) {
num_pds = data->num_pd_names;
by_id = false;
} else {
num_pds = of_count_phandle_with_args(np, "power-domains",
"#power-domain-cells");
}
if (num_pds <= 0)
return 0;
pds = devm_kzalloc(dev, sizeof(*pds), GFP_KERNEL);
if (!pds)
return -ENOMEM;
pds->pd_devs = devm_kcalloc(dev, num_pds, sizeof(*pds->pd_devs),
GFP_KERNEL);
if (!pds->pd_devs)
return -ENOMEM;
pds->pd_links = devm_kcalloc(dev, num_pds, sizeof(*pds->pd_links),
GFP_KERNEL);
if (!pds->pd_links)
return -ENOMEM;
if (link_flags && pd_flags & PD_FLAG_DEV_LINK_ON)
link_flags |= DL_FLAG_RPM_ACTIVE;
for (i = 0; i < num_pds; i++) {
if (by_id)
pd_dev = dev_pm_domain_attach_by_id(dev, i);
else
pd_dev = dev_pm_domain_attach_by_name(dev,
data->pd_names[i]);
if (IS_ERR_OR_NULL(pd_dev)) {
ret = pd_dev ? PTR_ERR(pd_dev) : -ENODEV;
goto err_attach;
}
if (link_flags) {
struct device_link *link;
link = device_link_add(dev, pd_dev, link_flags);
if (!link) {
ret = -ENODEV;
goto err_link;
}
pds->pd_links[i] = link;
}
pds->pd_devs[i] = pd_dev;
}
pds->num_pds = num_pds;
*list = pds;
return num_pds;
err_link:
dev_pm_domain_detach(pd_dev, true);
err_attach:
while (--i >= 0) {
if (pds->pd_links[i])
device_link_del(pds->pd_links[i]);
dev_pm_domain_detach(pds->pd_devs[i], true);
}
return ret;
}
EXPORT_SYMBOL_GPL(dev_pm_domain_attach_list);
/**
* dev_pm_domain_detach - Detach a device from its PM domain.
* @dev: Device to detach.
@@ -187,6 +296,31 @@ void dev_pm_domain_detach(struct device *dev, bool power_off)
}
EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
/**
* dev_pm_domain_detach_list - Detach a list of PM domains.
* @list: The list of PM domains to detach.
*
* This function reverse the actions from dev_pm_domain_attach_list().
* Typically it should be invoked during the remove phase from drivers.
*
* Callers must ensure proper synchronization of this function with power
* management callbacks.
*/
void dev_pm_domain_detach_list(struct dev_pm_domain_list *list)
{
int i;
if (!list)
return;
for (i = 0; i < list->num_pds; i++) {
if (list->pd_links[i])
device_link_del(list->pd_links[i]);
dev_pm_domain_detach(list->pd_devs[i], true);
}
}
EXPORT_SYMBOL_GPL(dev_pm_domain_detach_list);
/**
* dev_pm_domain_start - Start the device through its PM domain.
* @dev: Device to start.

View File

@@ -130,6 +130,7 @@ static const struct genpd_lock_ops genpd_spin_ops = {
#define genpd_is_active_wakeup(genpd) (genpd->flags & GENPD_FLAG_ACTIVE_WAKEUP)
#define genpd_is_cpu_domain(genpd) (genpd->flags & GENPD_FLAG_CPU_DOMAIN)
#define genpd_is_rpm_always_on(genpd) (genpd->flags & GENPD_FLAG_RPM_ALWAYS_ON)
#define genpd_is_opp_table_fw(genpd) (genpd->flags & GENPD_FLAG_OPP_TABLE_FW)
static inline bool irq_safe_dev_in_sleep_domain(struct device *dev,
const struct generic_pm_domain *genpd)
@@ -2319,7 +2320,7 @@ int of_genpd_add_provider_simple(struct device_node *np,
genpd->dev.of_node = np;
/* Parse genpd OPP table */
if (genpd->set_performance_state) {
if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) {
ret = dev_pm_opp_of_add_table(&genpd->dev);
if (ret)
return dev_err_probe(&genpd->dev, ret, "Failed to add OPP table\n");
@@ -2334,7 +2335,7 @@ int of_genpd_add_provider_simple(struct device_node *np,
ret = genpd_add_provider(np, genpd_xlate_simple, genpd);
if (ret) {
if (genpd->set_performance_state) {
if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) {
dev_pm_opp_put_opp_table(genpd->opp_table);
dev_pm_opp_of_remove_table(&genpd->dev);
}
@@ -2378,7 +2379,7 @@ int of_genpd_add_provider_onecell(struct device_node *np,
genpd->dev.of_node = np;
/* Parse genpd OPP table */
if (genpd->set_performance_state) {
if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) {
ret = dev_pm_opp_of_add_table_indexed(&genpd->dev, i);
if (ret) {
dev_err_probe(&genpd->dev, ret,
@@ -2414,7 +2415,7 @@ error:
genpd->provider = NULL;
genpd->has_provider = false;
if (genpd->set_performance_state) {
if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) {
dev_pm_opp_put_opp_table(genpd->opp_table);
dev_pm_opp_of_remove_table(&genpd->dev);
}
@@ -2446,7 +2447,7 @@ void of_genpd_del_provider(struct device_node *np)
if (gpd->provider == &np->fwnode) {
gpd->has_provider = false;
if (!gpd->set_performance_state)
if (genpd_is_opp_table_fw(gpd) || !gpd->set_performance_state)
continue;
dev_pm_opp_put_opp_table(gpd->opp_table);

View File

@@ -70,15 +70,35 @@ static unsigned int scmi_cpufreq_fast_switch(struct cpufreq_policy *policy,
return 0;
}
static int
scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
static int scmi_cpu_domain_id(struct device *cpu_dev)
{
int cpu, domain, tdomain;
struct device *tcpu_dev;
struct device_node *np = cpu_dev->of_node;
struct of_phandle_args domain_id;
int index;
domain = perf_ops->device_domain_id(cpu_dev);
if (domain < 0)
return domain;
if (of_parse_phandle_with_args(np, "clocks", "#clock-cells", 0,
&domain_id)) {
/* Find the corresponding index for power-domain "perf". */
index = of_property_match_string(np, "power-domain-names",
"perf");
if (index < 0)
return -EINVAL;
if (of_parse_phandle_with_args(np, "power-domains",
"#power-domain-cells", index,
&domain_id))
return -EINVAL;
}
return domain_id.args[0];
}
static int
scmi_get_sharing_cpus(struct device *cpu_dev, int domain,
struct cpumask *cpumask)
{
int cpu, tdomain;
struct device *tcpu_dev;
for_each_possible_cpu(cpu) {
if (cpu == cpu_dev->id)
@@ -88,7 +108,7 @@ scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
if (!tcpu_dev)
continue;
tdomain = perf_ops->device_domain_id(tcpu_dev);
tdomain = scmi_cpu_domain_id(tcpu_dev);
if (tdomain == domain)
cpumask_set_cpu(cpu, cpumask);
}
@@ -104,7 +124,7 @@ scmi_get_cpu_power(struct device *cpu_dev, unsigned long *power,
unsigned long Hz;
int ret, domain;
domain = perf_ops->device_domain_id(cpu_dev);
domain = scmi_cpu_domain_id(cpu_dev);
if (domain < 0)
return domain;
@@ -126,7 +146,7 @@ scmi_get_cpu_power(struct device *cpu_dev, unsigned long *power,
static int scmi_cpufreq_init(struct cpufreq_policy *policy)
{
int ret, nr_opp;
int ret, nr_opp, domain;
unsigned int latency;
struct device *cpu_dev;
struct scmi_data *priv;
@@ -138,6 +158,10 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
return -ENODEV;
}
domain = scmi_cpu_domain_id(cpu_dev);
if (domain < 0)
return domain;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
@@ -148,7 +172,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
}
/* Obtain CPUs that share SCMI performance controls */
ret = scmi_get_sharing_cpus(cpu_dev, policy->cpus);
ret = scmi_get_sharing_cpus(cpu_dev, domain, policy->cpus);
if (ret) {
dev_warn(cpu_dev, "failed to get sharing cpumask\n");
goto out_free_cpumask;
@@ -176,7 +200,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
*/
nr_opp = dev_pm_opp_get_opp_count(cpu_dev);
if (nr_opp <= 0) {
ret = perf_ops->device_opps_add(ph, cpu_dev);
ret = perf_ops->device_opps_add(ph, cpu_dev, domain);
if (ret) {
dev_warn(cpu_dev, "failed to add opps to the device\n");
goto out_free_cpumask;
@@ -209,7 +233,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
}
priv->cpu_dev = cpu_dev;
priv->domain_id = perf_ops->device_domain_id(cpu_dev);
priv->domain_id = domain;
policy->driver_data = priv;
policy->freq_table = freq_table;
@@ -217,14 +241,14 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
/* SCMI allows DVFS request for any domain from any CPU */
policy->dvfs_possible_from_any_cpu = true;
latency = perf_ops->transition_latency_get(ph, cpu_dev);
latency = perf_ops->transition_latency_get(ph, domain);
if (!latency)
latency = CPUFREQ_ETERNAL;
policy->cpuinfo.transition_latency = latency;
policy->fast_switch_possible =
perf_ops->fast_switch_possible(ph, cpu_dev);
perf_ops->fast_switch_possible(ph, domain);
return 0;

View File

@@ -124,7 +124,6 @@ struct scmi_msg_resp_perf_describe_levels {
struct perf_dom_info {
bool set_limits;
bool set_perf;
bool perf_limit_notify;
bool perf_level_notify;
bool perf_fastchannels;
@@ -132,7 +131,7 @@ struct perf_dom_info {
u32 sustained_freq_khz;
u32 sustained_perf_level;
unsigned long mult_factor;
char name[SCMI_MAX_STR_SIZE];
struct scmi_perf_domain_info info;
struct scmi_opp opp[MAX_OPPS];
struct scmi_fc_info *fc_info;
};
@@ -209,7 +208,7 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
flags = le32_to_cpu(attr->flags);
dom_info->set_limits = SUPPORTS_SET_LIMITS(flags);
dom_info->set_perf = SUPPORTS_SET_PERF_LVL(flags);
dom_info->info.set_perf = SUPPORTS_SET_PERF_LVL(flags);
dom_info->perf_limit_notify = SUPPORTS_PERF_LIMIT_NOTIFY(flags);
dom_info->perf_level_notify = SUPPORTS_PERF_LEVEL_NOTIFY(flags);
dom_info->perf_fastchannels = SUPPORTS_PERF_FASTCHANNELS(flags);
@@ -225,7 +224,8 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
dom_info->mult_factor =
(dom_info->sustained_freq_khz * 1000UL)
/ dom_info->sustained_perf_level;
strscpy(dom_info->name, attr->name, SCMI_SHORT_NAME_MAX_SIZE);
strscpy(dom_info->info.name, attr->name,
SCMI_SHORT_NAME_MAX_SIZE);
}
ph->xops->xfer_put(ph, t);
@@ -237,7 +237,7 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x3 &&
SUPPORTS_EXTENDED_NAMES(flags))
ph->hops->extended_name_get(ph, PERF_DOMAIN_NAME_GET, domain,
dom_info->name, SCMI_MAX_STR_SIZE);
dom_info->info.name, SCMI_MAX_STR_SIZE);
return ret;
}
@@ -333,6 +333,36 @@ scmi_perf_describe_levels_get(const struct scmi_protocol_handle *ph, u32 domain,
return ret;
}
static int scmi_perf_num_domains_get(const struct scmi_protocol_handle *ph)
{
struct scmi_perf_info *pi = ph->get_priv(ph);
return pi->num_domains;
}
static inline struct perf_dom_info *
scmi_perf_domain_lookup(const struct scmi_protocol_handle *ph, u32 domain)
{
struct scmi_perf_info *pi = ph->get_priv(ph);
if (domain >= pi->num_domains)
return ERR_PTR(-EINVAL);
return pi->dom_info + domain;
}
static const struct scmi_perf_domain_info *
scmi_perf_info_get(const struct scmi_protocol_handle *ph, u32 domain)
{
struct perf_dom_info *dom;
dom = scmi_perf_domain_lookup(ph, domain);
if (IS_ERR(dom))
return ERR_PTR(-EINVAL);
return &dom->info;
}
static int scmi_perf_mb_limits_set(const struct scmi_protocol_handle *ph,
u32 domain, u32 max_perf, u32 min_perf)
{
@@ -356,17 +386,6 @@ static int scmi_perf_mb_limits_set(const struct scmi_protocol_handle *ph,
return ret;
}
static inline struct perf_dom_info *
scmi_perf_domain_lookup(const struct scmi_protocol_handle *ph, u32 domain)
{
struct scmi_perf_info *pi = ph->get_priv(ph);
if (domain >= pi->num_domains)
return ERR_PTR(-EINVAL);
return pi->dom_info + domain;
}
static int scmi_perf_limits_set(const struct scmi_protocol_handle *ph,
u32 domain, u32 max_perf, u32 min_perf)
{
@@ -579,62 +598,43 @@ static void scmi_perf_domain_init_fc(const struct scmi_protocol_handle *ph,
*p_fc = fc;
}
/* Device specific ops */
static int scmi_dev_domain_id(struct device *dev)
{
struct of_phandle_args clkspec;
if (of_parse_phandle_with_args(dev->of_node, "clocks", "#clock-cells",
0, &clkspec))
return -EINVAL;
return clkspec.args[0];
}
static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph,
struct device *dev)
struct device *dev, u32 domain)
{
int idx, ret, domain;
int idx, ret;
unsigned long freq;
struct scmi_opp *opp;
struct dev_pm_opp_data data = {};
struct perf_dom_info *dom;
domain = scmi_dev_domain_id(dev);
if (domain < 0)
return -EINVAL;
dom = scmi_perf_domain_lookup(ph, domain);
if (IS_ERR(dom))
return PTR_ERR(dom);
for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) {
freq = opp->perf * dom->mult_factor;
for (idx = 0; idx < dom->opp_count; idx++) {
freq = dom->opp[idx].perf * dom->mult_factor;
ret = dev_pm_opp_add(dev, freq, 0);
data.level = dom->opp[idx].perf;
data.freq = freq;
ret = dev_pm_opp_add_dynamic(dev, &data);
if (ret) {
dev_warn(dev, "failed to add opp %luHz\n", freq);
while (idx-- > 0) {
freq = (--opp)->perf * dom->mult_factor;
dev_pm_opp_remove(dev, freq);
}
dev_pm_opp_remove_all_dynamic(dev);
return ret;
}
dev_dbg(dev, "[%d][%s]:: Registered OPP[%d] %lu\n",
domain, dom->info.name, idx, freq);
}
return 0;
}
static int
scmi_dvfs_transition_latency_get(const struct scmi_protocol_handle *ph,
struct device *dev)
u32 domain)
{
int domain;
struct perf_dom_info *dom;
domain = scmi_dev_domain_id(dev);
if (domain < 0)
return -EINVAL;
dom = scmi_perf_domain_lookup(ph, domain);
if (IS_ERR(dom))
return PTR_ERR(dom);
@@ -701,15 +701,10 @@ static int scmi_dvfs_est_power_get(const struct scmi_protocol_handle *ph,
}
static bool scmi_fast_switch_possible(const struct scmi_protocol_handle *ph,
struct device *dev)
u32 domain)
{
int domain;
struct perf_dom_info *dom;
domain = scmi_dev_domain_id(dev);
if (domain < 0)
return false;
dom = scmi_perf_domain_lookup(ph, domain);
if (IS_ERR(dom))
return false;
@@ -726,11 +721,12 @@ scmi_power_scale_get(const struct scmi_protocol_handle *ph)
}
static const struct scmi_perf_proto_ops perf_proto_ops = {
.num_domains_get = scmi_perf_num_domains_get,
.info_get = scmi_perf_info_get,
.limits_set = scmi_perf_limits_set,
.limits_get = scmi_perf_limits_get,
.level_set = scmi_perf_level_set,
.level_get = scmi_perf_level_get,
.device_domain_id = scmi_dev_domain_id,
.transition_latency_get = scmi_dvfs_transition_latency_get,
.device_opps_add = scmi_dvfs_device_opps_add,
.freq_set = scmi_dvfs_freq_set,

View File

@@ -44,6 +44,15 @@ static int virtio_pmem_flush(struct nd_region *nd_region)
unsigned long flags;
int err, err1;
/*
* Don't bother to submit the request to the device if the device is
* not activated.
*/
if (vdev->config->get_status(vdev) & VIRTIO_CONFIG_S_NEEDS_RESET) {
dev_info(&vdev->dev, "virtio pmem device needs a reset\n");
return -EIO;
}
might_sleep();
req_data = kmalloc(sizeof(*req_data), GFP_KERNEL);
if (!req_data)

View File

@@ -1011,6 +1011,28 @@ static int _set_required_opps(struct device *dev,
return ret;
}
static int _set_opp_level(struct device *dev, struct opp_table *opp_table,
struct dev_pm_opp *opp)
{
unsigned int level = 0;
int ret = 0;
if (opp) {
if (!opp->level)
return 0;
level = opp->level;
}
/* Request a new performance state through the device's PM domain. */
ret = dev_pm_genpd_set_performance_state(dev, level);
if (ret)
dev_err(dev, "Failed to set performance state %u (%d)\n", level,
ret);
return ret;
}
static void _find_current_opp(struct device *dev, struct opp_table *opp_table)
{
struct dev_pm_opp *opp = ERR_PTR(-ENODEV);
@@ -1058,8 +1080,13 @@ static int _disable_opp_table(struct device *dev, struct opp_table *opp_table)
if (opp_table->regulators)
regulator_disable(opp_table->regulators[0]);
ret = _set_opp_level(dev, opp_table, NULL);
if (ret)
goto out;
ret = _set_required_opps(dev, opp_table, NULL, false);
out:
opp_table->enabled = false;
return ret;
}
@@ -1102,6 +1129,10 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table,
return ret;
}
ret = _set_opp_level(dev, opp_table, opp);
if (ret)
return ret;
ret = _set_opp_bw(opp_table, opp, dev);
if (ret) {
dev_err(dev, "Failed to set bw: %d\n", ret);
@@ -1145,6 +1176,10 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table,
return ret;
}
ret = _set_opp_level(dev, opp_table, opp);
if (ret)
return ret;
ret = _set_required_opps(dev, opp_table, opp, false);
if (ret) {
dev_err(dev, "Failed to set required opps: %d\n", ret);
@@ -1914,8 +1949,7 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
* _opp_add_v1() - Allocate a OPP based on v1 bindings.
* @opp_table: OPP table
* @dev: device for which we do this operation
* @freq: Frequency in Hz for this OPP
* @u_volt: Voltage in uVolts for this OPP
* @data: The OPP data for the OPP to add
* @dynamic: Dynamically added OPPs.
*
* This function adds an opp definition to the opp table and returns status.
@@ -1933,10 +1967,10 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
* -ENOMEM Memory allocation failure
*/
int _opp_add_v1(struct opp_table *opp_table, struct device *dev,
unsigned long freq, long u_volt, bool dynamic)
struct dev_pm_opp_data *data, bool dynamic)
{
struct dev_pm_opp *new_opp;
unsigned long tol;
unsigned long tol, u_volt = data->u_volt;
int ret;
if (!assert_single_clk(opp_table))
@@ -1947,7 +1981,8 @@ int _opp_add_v1(struct opp_table *opp_table, struct device *dev,
return -ENOMEM;
/* populate the opp table */
new_opp->rates[0] = freq;
new_opp->rates[0] = data->freq;
new_opp->level = data->level;
tol = u_volt * opp_table->voltage_tolerance_v1 / 100;
new_opp->supplies[0].u_volt = u_volt;
new_opp->supplies[0].u_volt_min = u_volt - tol;
@@ -2731,10 +2766,9 @@ unlock:
}
/**
* dev_pm_opp_add() - Add an OPP table from a table definitions
* @dev: device for which we do this operation
* @freq: Frequency in Hz for this OPP
* @u_volt: Voltage in uVolts for this OPP
* dev_pm_opp_add_dynamic() - Add an OPP table from a table definitions
* @dev: The device for which we do this operation
* @data: The OPP data for the OPP to add
*
* This function adds an opp definition to the opp table and returns status.
* The opp is made available by default and it can be controlled using
@@ -2747,7 +2781,7 @@ unlock:
* Duplicate OPPs (both freq and volt are same) and !opp->available
* -ENOMEM Memory allocation failure
*/
int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
int dev_pm_opp_add_dynamic(struct device *dev, struct dev_pm_opp_data *data)
{
struct opp_table *opp_table;
int ret;
@@ -2759,12 +2793,24 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
/* Fix regulator count for dynamic OPPs */
opp_table->regulator_count = 1;
ret = _opp_add_v1(opp_table, dev, freq, u_volt, true);
ret = _opp_add_v1(opp_table, dev, data, true);
if (ret)
dev_pm_opp_put_opp_table(opp_table);
return ret;
}
EXPORT_SYMBOL_GPL(dev_pm_opp_add_dynamic);
int dev_pm_opp_add(struct device *dev, unsigned long freq,
unsigned long u_volt)
{
struct dev_pm_opp_data data = {
.freq = freq,
.u_volt = u_volt,
};
return dev_pm_opp_add_dynamic(dev, &data);
}
EXPORT_SYMBOL_GPL(dev_pm_opp_add);
/**

View File

@@ -1108,11 +1108,15 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table)
while (nr) {
unsigned long freq = be32_to_cpup(val++) * 1000;
unsigned long volt = be32_to_cpup(val++);
struct dev_pm_opp_data data = {
.freq = freq,
.u_volt = volt,
};
ret = _opp_add_v1(opp_table, dev, freq, volt, false);
ret = _opp_add_v1(opp_table, dev, &data, false);
if (ret) {
dev_err(dev, "%s: Failed to add OPP %ld (%d)\n",
__func__, freq, ret);
__func__, data.freq, ret);
goto remove_static_opp;
}
nr -= 2;

View File

@@ -252,7 +252,7 @@ struct dev_pm_opp *_opp_allocate(struct opp_table *opp_table);
void _opp_free(struct dev_pm_opp *opp);
int _opp_compare_key(struct opp_table *opp_table, struct dev_pm_opp *opp1, struct dev_pm_opp *opp2);
int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table);
int _opp_add_v1(struct opp_table *opp_table, struct device *dev, unsigned long freq, long u_volt, bool dynamic);
int _opp_add_v1(struct opp_table *opp_table, struct device *dev, struct dev_pm_opp_data *data, bool dynamic);
void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu);
struct opp_table *_add_opp_table_indexed(struct device *dev, int index, bool getclk);
void _put_opp_list_kref(struct opp_table *opp_table);

View File

@@ -1059,7 +1059,7 @@ static int brcmuart_probe(struct platform_device *pdev)
dev_dbg(dev, "DMA is %senabled\n", priv->dma_enabled ? "" : "not ");
memset(&up, 0, sizeof(up));
up.port.type = PORT_16550A;
up.port.type = PORT_BCM7271;
up.port.uartclk = clk_rate;
up.port.dev = dev;
up.port.mapbase = mapbase;
@@ -1073,8 +1073,6 @@ static int brcmuart_probe(struct platform_device *pdev)
| UPF_FIXED_PORT | UPF_FIXED_TYPE;
up.port.dev = dev;
up.port.private_data = priv;
up.capabilities = UART_CAP_FIFO | UART_CAP_AFE;
up.port.fifosize = 32;
/* Check for a fixed line number */
ret = of_alias_get_id(np, "serial");

View File

@@ -314,6 +314,14 @@ static const struct serial8250_config uart_config[] = {
.rxtrig_bytes = {1, 4, 8, 14},
.flags = UART_CAP_FIFO,
},
[PORT_BCM7271] = {
.name = "Broadcom BCM7271 UART",
.fifo_size = 32,
.tx_loadsz = 32,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01,
.rxtrig_bytes = {1, 8, 16, 30},
.flags = UART_CAP_FIFO | UART_CAP_AFE,
},
};
/* Uart divisor latch read */

View File

@@ -105,16 +105,15 @@ EXPORT_SYMBOL_GPL(ufshcd_mcq_config_mac);
* @hba: per adapter instance
* @req: pointer to the request to be issued
*
* Returns the hardware queue instance on which the request would
* be queued.
* Return: the hardware queue instance on which the request will be or has
* been queued. %NULL if the request has already been freed.
*/
struct ufs_hw_queue *ufshcd_mcq_req_to_hwq(struct ufs_hba *hba,
struct request *req)
{
u32 utag = blk_mq_unique_tag(req);
u32 hwq = blk_mq_unique_tag_to_hwq(utag);
struct blk_mq_hw_ctx *hctx = READ_ONCE(req->mq_hctx);
return &hba->uhq[hwq];
return hctx ? &hba->uhq[hctx->queue_num] : NULL;
}
/**
@@ -521,6 +520,8 @@ int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag)
if (!cmd)
return -EINVAL;
hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(cmd));
if (!hwq)
return 0;
} else {
hwq = hba->dev_cmd_queue;
}

View File

@@ -6489,6 +6489,8 @@ static bool ufshcd_abort_all(struct ufs_hba *hba)
goto out;
}
hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(lrbp->cmd));
if (!hwq)
return 0;
spin_lock_irqsave(&hwq->cq_lock, flags);
if (ufshcd_cmd_inflight(lrbp->cmd))
ufshcd_release_scsi_cmd(hba, lrbp);

View File

@@ -2453,7 +2453,7 @@ static int tcpm_register_sink_caps(struct tcpm_port *port)
{
struct usb_power_delivery_desc desc = { port->negotiated_rev };
struct usb_power_delivery_capabilities_desc caps = { };
struct usb_power_delivery_capabilities *cap = port->partner_source_caps;
struct usb_power_delivery_capabilities *cap;
if (!port->partner_pd)
port->partner_pd = usb_power_delivery_register(NULL, &desc);
@@ -2463,11 +2463,6 @@ static int tcpm_register_sink_caps(struct tcpm_port *port)
memcpy(caps.pdo, port->sink_caps, sizeof(u32) * port->nr_sink_caps);
caps.role = TYPEC_SINK;
if (cap) {
usb_power_delivery_unregister_capabilities(cap);
port->partner_source_caps = NULL;
}
cap = usb_power_delivery_register_capabilities(port->partner_pd, &caps);
if (IS_ERR(cap))
return PTR_ERR(cap);

View File

@@ -111,7 +111,8 @@ int z_erofs_gbuf_growsize(unsigned int nrpages)
out:
if (i < z_erofs_gbuf_count && tmp_pages) {
for (j = 0; j < nrpages; ++j)
if (tmp_pages[j] && tmp_pages[j] != gbuf->pages[j])
if (tmp_pages[j] && (j >= gbuf->nrpages ||
tmp_pages[j] != gbuf->pages[j]))
__free_page(tmp_pages[j]);
kfree(tmp_pages);
}

View File

@@ -73,6 +73,7 @@
#include "internal.h"
#include <trace/events/sched.h>
#include <trace/hooks/sched.h>
static int bprm_creds_from_file(struct linux_binprm *bprm);
@@ -1238,6 +1239,7 @@ void __set_task_comm(struct task_struct *tsk, const char *buf, bool exec)
task_lock(tsk);
trace_task_rename(tsk, buf);
strscpy_pad(tsk->comm, buf, sizeof(tsk->comm));
trace_android_vh_set_task_comm(tsk);
task_unlock(tsk);
perf_event_comm(tsk, exec);
}

View File

@@ -798,6 +798,7 @@ enum {
FI_ALIGNED_WRITE, /* enable aligned write */
FI_COW_FILE, /* indicate COW file */
FI_ATOMIC_COMMITTED, /* indicate atomic commit completed except disk sync */
FI_ATOMIC_DIRTIED, /* indicate atomic file is dirtied */
FI_ATOMIC_REPLACE, /* indicate atomic replace */
FI_MAX, /* max flag, never be used */
};
@@ -3001,7 +3002,6 @@ static inline void __mark_inode_dirty_flag(struct inode *inode,
case FI_INLINE_DOTS:
case FI_PIN_FILE:
case FI_COMPRESS_RELEASED:
case FI_ATOMIC_COMMITTED:
f2fs_mark_inode_dirty_sync(inode, true);
}
}

View File

@@ -33,6 +33,11 @@ void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync)
if (f2fs_inode_dirtied(inode, sync))
return;
if (f2fs_is_atomic_file(inode)) {
set_inode_flag(inode, FI_ATOMIC_DIRTIED);
return;
}
mark_inode_dirty_sync(inode);
}

View File

@@ -199,6 +199,10 @@ void f2fs_abort_atomic_write(struct inode *inode, bool clean)
clear_inode_flag(inode, FI_ATOMIC_COMMITTED);
clear_inode_flag(inode, FI_ATOMIC_REPLACE);
clear_inode_flag(inode, FI_ATOMIC_FILE);
if (is_inode_flag_set(inode, FI_ATOMIC_DIRTIED)) {
clear_inode_flag(inode, FI_ATOMIC_DIRTIED);
f2fs_mark_inode_dirty_sync(inode, true);
}
stat_dec_atomic_inode(inode);
F2FS_I(inode)->atomic_write_task = NULL;
@@ -368,6 +372,10 @@ out:
} else {
sbi->committed_atomic_block += fi->atomic_write_cnt;
set_inode_flag(inode, FI_ATOMIC_COMMITTED);
if (is_inode_flag_set(inode, FI_ATOMIC_DIRTIED)) {
clear_inode_flag(inode, FI_ATOMIC_DIRTIED);
f2fs_mark_inode_dirty_sync(inode, true);
}
}
__complete_revoke_list(inode, &revoke_list, ret ? true : false);

View File

@@ -27,6 +27,7 @@
#include <linux/sizes.h>
#include <linux/sched.h>
#include <linux/pgtable.h>
#include <linux/pgsize_migration_inline.h>
#include <linux/kasan.h>
#include <linux/page_pinner.h>
#include <linux/memremap.h>
@@ -834,6 +835,8 @@ static inline void vm_flags_reset(struct vm_area_struct *vma,
vm_flags_t flags)
{
vma_assert_write_locked(vma);
/* Preserve padding flags */
flags = vma_pad_fixup_flags(vma, flags);
vm_flags_init(vma, flags);
}
@@ -841,6 +844,8 @@ static inline void vm_flags_reset_once(struct vm_area_struct *vma,
vm_flags_t flags)
{
vma_assert_write_locked(vma);
/* Preserve padding flags */
flags = vma_pad_fixup_flags(vma, flags);
WRITE_ONCE(ACCESS_PRIVATE(vma, __vm_flags), flags);
}

View File

@@ -13,35 +13,9 @@
* page size in Android.
*/
#include <linux/mm.h>
#include <linux/pgsize_migration_inline.h>
#include <linux/seq_file.h>
#include <linux/sizes.h>
/*
* vm_flags representation of VMA padding pages.
*
* This allows the kernel to identify the portion of an ELF LOAD segment VMA
* that is padding.
*
* 4 high bits of vm_flags [63,60] are used to represent ELF segment padding
* up to 60kB, which is sufficient for ELFs of both 16kB and 64kB segment
* alignment (p_align).
*
* The representation is illustrated below.
*
* 63 62 61 60
* _________ _________ _________ _________
* | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
* | of 4kB | of 4kB | of 4kB | of 4kB |
* | chunks | chunks | chunks | chunks |
* |_________|_________|_________|_________|
*/
#define VM_PAD_WIDTH 4
#define VM_PAD_SHIFT (BITS_PER_LONG - VM_PAD_WIDTH)
#define VM_TOTAL_PAD_PAGES ((1ULL << VM_PAD_WIDTH) - 1)
#define VM_PAD_MASK (VM_TOTAL_PAD_PAGES << VM_PAD_SHIFT)
#define VMA_PAD_START(vma) (vma->vm_end - (vma_pad_pages(vma) << PAGE_SHIFT))
#include <linux/mm.h>
#if PAGE_SIZE == SZ_4K && defined(CONFIG_64BIT)
extern void vma_set_pad_pages(struct vm_area_struct *vma,
@@ -63,9 +37,6 @@ extern void show_map_pad_vma(struct vm_area_struct *vma,
extern void split_pad_vma(struct vm_area_struct *vma, struct vm_area_struct *new,
unsigned long addr, int new_below);
extern unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
unsigned long newflags);
extern bool is_mergable_pad_vma(struct vm_area_struct *vma,
unsigned long vm_flags);
@@ -107,12 +78,6 @@ static inline void split_pad_vma(struct vm_area_struct *vma, struct vm_area_stru
{
}
static inline unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
unsigned long newflags)
{
return newflags;
}
static inline bool is_mergable_pad_vma(struct vm_area_struct *vma,
unsigned long vm_flags)
{

View File

@@ -0,0 +1,67 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_PAGE_SIZE_MIGRATION_INLINE_H
#define _LINUX_PAGE_SIZE_MIGRATION_INLINE_H
/*
* Page Size Migration
*
* Copyright (c) 2024, Google LLC.
* Author: Kalesh Singh <kaleshsingh@goole.com>
*
* This file contains inline APIs for mitigations to ensure
* app compatibility during the transition from 4kB to 16kB
* page size in Android.
*/
#include <linux/mm_types.h>
#include <linux/sizes.h>
#include <asm/page.h>
/*
* vm_flags representation of VMA padding pages.
*
* This allows the kernel to identify the portion of an ELF LOAD segment VMA
* that is padding.
*
* 4 high bits of vm_flags [63,60] are used to represent ELF segment padding
* up to 60kB, which is sufficient for ELFs of both 16kB and 64kB segment
* alignment (p_align).
*
* The representation is illustrated below.
*
* 63 62 61 60
* _________ _________ _________ _________
* | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
* | of 4kB | of 4kB | of 4kB | of 4kB |
* | chunks | chunks | chunks | chunks |
* |_________|_________|_________|_________|
*/
#define VM_PAD_WIDTH 4
#define VM_PAD_SHIFT (BITS_PER_LONG - VM_PAD_WIDTH)
#define VM_TOTAL_PAD_PAGES ((1ULL << VM_PAD_WIDTH) - 1)
#define VM_PAD_MASK (VM_TOTAL_PAD_PAGES << VM_PAD_SHIFT)
#define VMA_PAD_START(vma) (vma->vm_end - (vma_pad_pages(vma) << PAGE_SHIFT))
#if PAGE_SIZE == SZ_4K && defined(CONFIG_64BIT)
/*
* Sets the correct padding bits / flags for a VMA split.
*/
static inline unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
unsigned long newflags)
{
if (newflags & VM_PAD_MASK)
return (newflags & ~VM_PAD_MASK) | (vma->vm_flags & VM_PAD_MASK);
else
return newflags;
}
#else /* PAGE_SIZE != SZ_4K || !defined(CONFIG_64BIT) */
static inline unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
unsigned long newflags)
{
return newflags;
}
#endif /* PAGE_SIZE == SZ_4K && defined(CONFIG_64BIT) */
#endif /* _LINUX_PAGE_SIZE_MIGRATION_INLINE_H */

View File

@@ -18,6 +18,33 @@
#include <linux/spinlock.h>
#include <linux/cpumask.h>
/*
* Flags to control the behaviour when attaching a device to its PM domains.
*
* PD_FLAG_NO_DEV_LINK: As the default behaviour creates a device-link
* for every PM domain that gets attached, this
* flag can be used to skip that.
*
* PD_FLAG_DEV_LINK_ON: Add the DL_FLAG_RPM_ACTIVE to power-on the
* supplier and its PM domain when creating the
* device-links.
*
*/
#define PD_FLAG_NO_DEV_LINK BIT(0)
#define PD_FLAG_DEV_LINK_ON BIT(1)
struct dev_pm_domain_attach_data {
const char * const *pd_names;
const u32 num_pd_names;
const u32 pd_flags;
};
struct dev_pm_domain_list {
struct device **pd_devs;
struct device_link **pd_links;
u32 num_pds;
};
/*
* Flags to control the behaviour of a genpd.
*
@@ -60,6 +87,10 @@
* GENPD_FLAG_MIN_RESIDENCY: Enable the genpd governor to consider its
* components' next wakeup when determining the
* optimal idle state.
*
* GENPD_FLAG_OPP_TABLE_FW: The genpd provider supports performance states,
* but its corresponding OPP tables are not
* described in DT, but are given directly by FW.
*/
#define GENPD_FLAG_PM_CLK (1U << 0)
#define GENPD_FLAG_IRQ_SAFE (1U << 1)
@@ -68,6 +99,7 @@
#define GENPD_FLAG_CPU_DOMAIN (1U << 4)
#define GENPD_FLAG_RPM_ALWAYS_ON (1U << 5)
#define GENPD_FLAG_MIN_RESIDENCY (1U << 6)
#define GENPD_FLAG_OPP_TABLE_FW (1U << 7)
enum gpd_status {
GENPD_STATE_ON = 0, /* PM domain is on */
@@ -415,7 +447,11 @@ struct device *dev_pm_domain_attach_by_id(struct device *dev,
unsigned int index);
struct device *dev_pm_domain_attach_by_name(struct device *dev,
const char *name);
int dev_pm_domain_attach_list(struct device *dev,
const struct dev_pm_domain_attach_data *data,
struct dev_pm_domain_list **list);
void dev_pm_domain_detach(struct device *dev, bool power_off);
void dev_pm_domain_detach_list(struct dev_pm_domain_list *list);
int dev_pm_domain_start(struct device *dev);
void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd);
#else
@@ -433,7 +469,14 @@ static inline struct device *dev_pm_domain_attach_by_name(struct device *dev,
{
return NULL;
}
static inline int dev_pm_domain_attach_list(struct device *dev,
const struct dev_pm_domain_attach_data *data,
struct dev_pm_domain_list **list)
{
return 0;
}
static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {}
static inline void dev_pm_domain_detach_list(struct dev_pm_domain_list *list) {}
static inline int dev_pm_domain_start(struct device *dev)
{
return 0;

View File

@@ -92,6 +92,18 @@ struct dev_pm_opp_config {
struct device ***virt_devs;
};
/**
* struct dev_pm_opp_data - The data to use to initialize an OPP.
* @level: The performance level for the OPP.
* @freq: The clock rate in Hz for the OPP.
* @u_volt: The voltage in uV for the OPP.
*/
struct dev_pm_opp_data {
unsigned int level;
unsigned long freq;
unsigned long u_volt;
};
#if defined(CONFIG_PM_OPP)
struct opp_table *dev_pm_opp_get_opp_table(struct device *dev);
@@ -140,8 +152,9 @@ struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev,
void dev_pm_opp_put(struct dev_pm_opp *opp);
int dev_pm_opp_add(struct device *dev, unsigned long freq,
unsigned long u_volt);
int dev_pm_opp_add_dynamic(struct device *dev, struct dev_pm_opp_data *opp);
int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt);
void dev_pm_opp_remove(struct device *dev, unsigned long freq);
void dev_pm_opp_remove_all_dynamic(struct device *dev);
@@ -291,8 +304,14 @@ static inline struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev,
static inline void dev_pm_opp_put(struct dev_pm_opp *opp) {}
static inline int dev_pm_opp_add(struct device *dev, unsigned long freq,
unsigned long u_volt)
static inline int
dev_pm_opp_add_dynamic(struct device *dev, struct dev_pm_opp_data *opp)
{
return -EOPNOTSUPP;
}
static inline int
dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
{
return -EOPNOTSUPP;
}

View File

@@ -100,15 +100,21 @@ struct scmi_clk_proto_ops {
ANDROID_KABI_RESERVE(1);
};
struct scmi_perf_domain_info {
char name[SCMI_MAX_STR_SIZE];
bool set_perf;
};
/**
* struct scmi_perf_proto_ops - represents the various operations provided
* by SCMI Performance Protocol
*
* @num_domains_get: gets the number of supported performance domains
* @info_get: get the information of a performance domain
* @limits_set: sets limits on the performance level of a domain
* @limits_get: gets limits on the performance level of a domain
* @level_set: sets the performance level of a domain
* @level_get: gets the performance level of a domain
* @device_domain_id: gets the scmi domain id for a given device
* @transition_latency_get: gets the DVFS transition latency for a given device
* @device_opps_add: adds all the OPPs for a given device
* @freq_set: sets the frequency for a given device using sustained frequency
@@ -123,6 +129,9 @@ struct scmi_clk_proto_ops {
* or in some other (abstract) scale
*/
struct scmi_perf_proto_ops {
int (*num_domains_get)(const struct scmi_protocol_handle *ph);
const struct scmi_perf_domain_info __must_check *(*info_get)
(const struct scmi_protocol_handle *ph, u32 domain);
int (*limits_set)(const struct scmi_protocol_handle *ph, u32 domain,
u32 max_perf, u32 min_perf);
int (*limits_get)(const struct scmi_protocol_handle *ph, u32 domain,
@@ -131,11 +140,10 @@ struct scmi_perf_proto_ops {
u32 level, bool poll);
int (*level_get)(const struct scmi_protocol_handle *ph, u32 domain,
u32 *level, bool poll);
int (*device_domain_id)(struct device *dev);
int (*transition_latency_get)(const struct scmi_protocol_handle *ph,
struct device *dev);
u32 domain);
int (*device_opps_add)(const struct scmi_protocol_handle *ph,
struct device *dev);
struct device *dev, u32 domain);
int (*freq_set)(const struct scmi_protocol_handle *ph, u32 domain,
unsigned long rate, bool poll);
int (*freq_get)(const struct scmi_protocol_handle *ph, u32 domain,
@@ -143,7 +151,7 @@ struct scmi_perf_proto_ops {
int (*est_power_get)(const struct scmi_protocol_handle *ph, u32 domain,
unsigned long *rate, unsigned long *power);
bool (*fast_switch_possible)(const struct scmi_protocol_handle *ph,
struct device *dev);
u32 domain);
enum scmi_power_scale (*power_scale_get)(const struct scmi_protocol_handle *ph);
ANDROID_KABI_RESERVE(1);

View File

@@ -145,6 +145,9 @@ DECLARE_HOOK(android_vh_mm_compaction_begin,
DECLARE_HOOK(android_vh_mm_compaction_end,
TP_PROTO(struct compact_control *cc, long vendor_ret),
TP_ARGS(cc, vendor_ret));
DECLARE_HOOK(android_vh_mm_kcompactd_cpu_online,
TP_PROTO(int cpu),
TP_ARGS(cpu));
DECLARE_HOOK(android_vh_free_unref_page_bypass,
TP_PROTO(struct page *page, int order, int migratetype, bool *bypass),
TP_ARGS(page, order, migratetype, bypass));
@@ -208,6 +211,9 @@ DECLARE_HOOK(android_vh_look_around,
DECLARE_HOOK(android_vh_mm_alloc_pages_direct_reclaim_enter,
TP_PROTO(unsigned int order),
TP_ARGS(order));
DECLARE_HOOK(android_vh_should_fault_around,
TP_PROTO(struct vm_fault *vmf, bool *should_around),
TP_ARGS(vmf, should_around));
DECLARE_HOOK(android_vh_mm_alloc_pages_direct_reclaim_exit,
TP_PROTO(unsigned long did_some_progress, int retry_times),
TP_ARGS(did_some_progress, retry_times));
@@ -246,6 +252,36 @@ DECLARE_HOOK(android_vh_shmem_swapin_folio,
DECLARE_HOOK(android_vh_madvise_cold_or_pageout_page,
TP_PROTO(bool pageout, struct page *page),
TP_ARGS(pageout, page));
DECLARE_HOOK(android_vh_page_should_be_protected,
TP_PROTO(struct folio *folio, unsigned long nr_scanned,
s8 priority, u64 *ext, int *should_protect),
TP_ARGS(folio, nr_scanned, priority, ext, should_protect));
DECLARE_HOOK(android_vh_swapmem_gather_init,
TP_PROTO(struct mm_struct *mm),
TP_ARGS(mm));
DECLARE_HOOK(android_vh_swapmem_gather_add_bypass,
TP_PROTO(struct mm_struct *mm, swp_entry_t entry, bool *bypass),
TP_ARGS(mm, entry, bypass));
DECLARE_HOOK(android_vh_swapmem_gather_finish,
TP_PROTO(struct mm_struct *mm),
TP_ARGS(mm));
DECLARE_HOOK(android_vh_oom_swapmem_gather_init,
TP_PROTO(struct mm_struct *mm),
TP_ARGS(mm));
DECLARE_HOOK(android_vh_oom_swapmem_gather_finish,
TP_PROTO(struct mm_struct *mm),
TP_ARGS(mm));
DECLARE_HOOK(android_vh_do_read_fault,
TP_PROTO(struct vm_fault *vmf, unsigned long fault_around_bytes),
TP_ARGS(vmf, fault_around_bytes));
DECLARE_HOOK(android_vh_filemap_read,
TP_PROTO(struct file *file, loff_t pos, size_t size),
TP_ARGS(file, pos, size));
DECLARE_HOOK(android_vh_filemap_map_pages,
TP_PROTO(struct file *file, pgoff_t first_pgoff,
pgoff_t last_pgoff, vm_fault_t ret),
TP_ARGS(file, first_pgoff, last_pgoff, ret));
#endif /* _TRACE_HOOK_MM_H */
/* This part must be outside protection */

View File

@@ -458,6 +458,10 @@ DECLARE_HOOK(android_vh_prio_restore,
TP_PROTO(int saved_prio),
TP_ARGS(saved_prio));
DECLARE_HOOK(android_vh_set_task_comm,
TP_PROTO(struct task_struct *p),
TP_ARGS(p));
#endif /* _TRACE_HOOK_SCHED_H */
/* This part must be outside protection */
#include <trace/define_trace.h>

View File

@@ -69,6 +69,9 @@ DECLARE_HOOK(android_vh_do_folio_trylock,
TP_PROTO(struct folio *folio, struct rw_semaphore *sem,
bool *got_lock, bool *skip),
TP_ARGS(folio, sem, got_lock, skip));
DECLARE_HOOK(android_vh_page_referenced_check_bypass,
TP_PROTO(struct folio *folio, unsigned long nr_to_scan, int lru, bool *bypass),
TP_ARGS(folio, nr_to_scan, lru, bypass));
#endif /* _TRACE_HOOK_VMSCAN_H */
/* This part must be outside protection */
#include <trace/define_trace.h>

View File

@@ -284,6 +284,12 @@ struct binder_frozen_status_info {
__u32 async_recv;
};
struct binder_frozen_state_info {
binder_uintptr_t cookie;
__u32 is_frozen;
__u32 reserved;
};
/* struct binder_extened_error - extended error information
* @id: identifier for the failed operation
* @command: command as defined by binder_driver_return_protocol
@@ -508,6 +514,17 @@ enum binder_driver_return_protocol {
* asynchronous transaction makes the allocated async buffer size exceed
* detection threshold. No parameters.
*/
BR_FROZEN_BINDER = _IOR('r', 21, struct binder_frozen_state_info),
/*
* The cookie and a boolean (is_frozen) that indicates whether the process
* transitioned into a frozen or an unfrozen state.
*/
BR_CLEAR_FREEZE_NOTIFICATION_DONE = _IOR('r', 22, binder_uintptr_t),
/*
* void *: cookie
*/
};
enum binder_driver_command_protocol {
@@ -591,6 +608,25 @@ enum binder_driver_command_protocol {
/*
* binder_transaction_data_sg: the sent command.
*/
BC_REQUEST_FREEZE_NOTIFICATION =
_IOW('c', 19, struct binder_handle_cookie),
/*
* int: handle
* void *: cookie
*/
BC_CLEAR_FREEZE_NOTIFICATION = _IOW('c', 20,
struct binder_handle_cookie),
/*
* int: handle
* void *: cookie
*/
BC_FREEZE_NOTIFICATION_DONE = _IOW('c', 21, binder_uintptr_t),
/*
* void *: cookie
*/
};
#endif /* _UAPI_LINUX_BINDER_H */

View File

@@ -144,6 +144,9 @@
/* Blackfin bf5xx */
#define PORT_BFIN 75
/* Broadcom BCM7271 UART */
#define PORT_BCM7271 76
/* Broadcom SB1250, etc. SOC */
#define PORT_SB1250_DUART 77

View File

@@ -13328,7 +13328,8 @@ static int inherit_group(struct perf_event *parent_event,
!perf_get_aux_event(child_ctr, leader))
return -EINVAL;
}
leader->group_generation = parent_event->group_generation;
if (leader)
leader->group_generation = parent_event->group_generation;
return 0;
}

View File

@@ -721,7 +721,6 @@ static void update_rq_clock_task(struct rq *rq, s64 delta)
rq->prev_irq_time += irq_delta;
delta -= irq_delta;
psi_account_irqtime(rq->curr, irq_delta);
#endif
#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
if (static_key_false((&paravirt_steal_rq_enabled))) {
@@ -5679,7 +5678,7 @@ void scheduler_tick(void)
{
int cpu = smp_processor_id();
struct rq *rq = cpu_rq(cpu);
struct task_struct *curr = rq->curr;
struct task_struct *curr;
struct rq_flags rf;
unsigned long thermal_pressure;
u64 resched_latency;
@@ -5691,6 +5690,9 @@ void scheduler_tick(void)
rq_lock(rq, &rf);
curr = rq->curr;
psi_account_irqtime(rq, curr, NULL);
update_rq_clock(rq);
trace_android_rvh_tick_entry(rq);
@@ -6736,6 +6738,7 @@ static void __sched notrace __schedule(unsigned int sched_mode)
++*switch_count;
migrate_disable_switch(rq, prev);
psi_account_irqtime(rq, prev, next);
psi_sched_switch(prev, next, !task_on_rq_queued(prev));
trace_sched_switch(sched_mode & SM_MASK_PREEMPT, prev, next, prev_state);

View File

@@ -737,6 +737,7 @@ static void psi_group_change(struct psi_group *group, int cpu,
enum psi_states s;
u32 state_mask;
lockdep_assert_rq_held(cpu_rq(cpu));
groupc = per_cpu_ptr(group->pcpu, cpu);
/*
@@ -955,19 +956,31 @@ void psi_task_switch(struct task_struct *prev, struct task_struct *next,
}
#ifdef CONFIG_IRQ_TIME_ACCOUNTING
void psi_account_irqtime(struct task_struct *task, u32 delta)
static DEFINE_PER_CPU(u64, psi_irq_time);
void psi_account_irqtime(struct rq *rq, struct task_struct *curr, struct task_struct *prev)
{
int cpu = task_cpu(task);
int cpu = task_cpu(curr);
struct psi_group *group;
struct psi_group_cpu *groupc;
u64 now;
u64 now, irq, *psi_time;
s64 delta;
if (!task->pid)
if (!curr->pid)
return;
lockdep_assert_rq_held(rq);
group = task_psi_group(curr);
if (prev && task_psi_group(prev) == group)
return;
now = cpu_clock(cpu);
irq = irq_time_read(cpu);
psi_time = &per_cpu(psi_irq_time, cpu);
delta = (s64)(irq - *psi_time);
if (delta < 0)
return;
*psi_time = irq;
group = task_psi_group(task);
do {
if (!group->enabled)
continue;

View File

@@ -110,8 +110,12 @@ __schedstats_from_se(struct sched_entity *se)
void psi_task_change(struct task_struct *task, int clear, int set);
void psi_task_switch(struct task_struct *prev, struct task_struct *next,
bool sleep);
void psi_account_irqtime(struct task_struct *task, u32 delta);
#ifdef CONFIG_IRQ_TIME_ACCOUNTING
void psi_account_irqtime(struct rq *rq, struct task_struct *curr, struct task_struct *prev);
#else
static inline void psi_account_irqtime(struct rq *rq, struct task_struct *curr,
struct task_struct *prev) {}
#endif /*CONFIG_IRQ_TIME_ACCOUNTING */
/*
* PSI tracks state that persists across sleeps, such as iowaits and
* memory stalls. As a result, it has to distinguish between sleeps,
@@ -206,7 +210,8 @@ static inline void psi_ttwu_dequeue(struct task_struct *p) {}
static inline void psi_sched_switch(struct task_struct *prev,
struct task_struct *next,
bool sleep) {}
static inline void psi_account_irqtime(struct task_struct *task, u32 delta) {}
static inline void psi_account_irqtime(struct rq *rq, struct task_struct *curr,
struct task_struct *prev) {}
#endif /* CONFIG_PSI */
#ifdef CONFIG_SCHED_INFO

View File

@@ -115,3 +115,4 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_update_blocked_fair);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_update_rt_rq_load_avg);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_prio_inheritance);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_prio_restore);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_set_task_comm);

View File

@@ -44,3 +44,4 @@ void __show_mem(unsigned int filter, nodemask_t *nodemask, int max_zone_idx)
#endif
trace_android_vh_show_mem(filter, nodemask);
}
EXPORT_SYMBOL_GPL(__show_mem);

View File

@@ -3070,6 +3070,7 @@ static int kcompactd_cpu_online(unsigned int cpu)
if (pgdat->kcompactd)
set_cpus_allowed_ptr(pgdat->kcompactd, mask);
}
trace_android_vh_mm_kcompactd_cpu_online(cpu);
return 0;
}

View File

@@ -2736,6 +2736,7 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter,
iov_iter_truncate(iter, inode->i_sb->s_maxbytes);
folio_batch_init(&fbatch);
trace_android_vh_filemap_read(filp, iocb->ki_pos, iov_iter_count(iter));
do {
cond_resched();
@@ -3438,11 +3439,13 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf,
struct page *page;
unsigned int mmap_miss = READ_ONCE(file->f_ra.mmap_miss);
vm_fault_t ret = 0;
pgoff_t first_pgoff = 0;
rcu_read_lock();
folio = first_map_page(mapping, &xas, end_pgoff);
if (!folio)
goto out;
first_pgoff = xas.xa_index;
if (filemap_map_pmd(vmf, &folio->page)) {
ret = VM_FAULT_NOPAGE;
@@ -3498,6 +3501,8 @@ unlock:
out:
rcu_read_unlock();
WRITE_ONCE(file->f_ra.mmap_miss, mmap_miss);
trace_android_vh_filemap_map_pages(file, first_pgoff, last_pgoff, ret);
return ret;
}
EXPORT_SYMBOL(filemap_map_pages);

View File

@@ -81,6 +81,7 @@
#include <linux/set_memory.h>
#include <trace/events/kmem.h>
#include <trace/hooks/mm.h>
#undef CREATE_TRACE_POINTS
#include <trace/hooks/mm.h>
@@ -1426,6 +1427,7 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
pte_t *start_pte;
pte_t *pte;
swp_entry_t entry;
bool bypass = false;
tlb_change_page_size(tlb, PAGE_SIZE);
again:
@@ -1498,6 +1500,9 @@ again:
if (!should_zap_cows(details))
continue;
rss[MM_SWAPENTS]--;
trace_android_vh_swapmem_gather_add_bypass(mm, entry, &bypass);
if (bypass)
goto skip;
if (unlikely(!free_swap_and_cache(entry)))
print_bad_pte(vma, addr, ptent, NULL);
} else if (is_migration_entry(entry)) {
@@ -1517,6 +1522,7 @@ again:
/* We should have covered all the swap entry types */
WARN_ON_ONCE(1);
}
skip:
pte_clear_not_present_full(mm, addr, pte, tlb->fullmm);
zap_install_uffd_wp_if_needed(vma, addr, pte, details, ptent);
} while (pte++, addr += PAGE_SIZE, addr != end);
@@ -4658,6 +4664,7 @@ static vm_fault_t do_fault_around(struct vm_fault *vmf)
/* Return true if we should do read fault-around, false otherwise */
static inline bool should_fault_around(struct vm_fault *vmf)
{
bool should_around = true;
/* No ->map_pages? No way to fault around... */
if (!vmf->vma->vm_ops->map_pages)
return false;
@@ -4665,6 +4672,10 @@ static inline bool should_fault_around(struct vm_fault *vmf)
if (uffd_disable_fault_around(vmf->vma))
return false;
trace_android_vh_should_fault_around(vmf, &should_around);
if (!should_around)
return false;
return fault_around_bytes >> PAGE_SHIFT > 1;
}
@@ -4685,6 +4696,8 @@ static vm_fault_t do_read_fault(struct vm_fault *vmf)
ret = do_fault_around(vmf);
if (ret)
return ret;
} else {
trace_android_vh_do_read_fault(vmf, fault_around_bytes);
}
ret = vmf_can_call_fault(vmf);

View File

@@ -459,7 +459,7 @@ success:
if ((newflags & VM_LOCKED) && (oldflags & VM_LOCKED)) {
/* No work to do, and mlocking twice would be wrong */
vma_start_write(vma);
vm_flags_reset(vma, vma_pad_fixup_flags(vma, newflags));
vm_flags_reset(vma, newflags);
} else {
mlock_vma_pages_range(vma, start, end, newflags);
}

View File

@@ -3329,9 +3329,11 @@ void exit_mmap(struct mm_struct *mm)
lru_add_drain();
flush_cache_mm(mm);
tlb_gather_mmu_fullmm(&tlb, mm);
trace_android_vh_swapmem_gather_init(mm);
/* update_hiwater_rss(mm) here? but nobody should be looking */
/* Use ULONG_MAX here to ensure all VMAs in the mm are unmapped */
unmap_vmas(&tlb, &mm->mm_mt, vma, 0, ULONG_MAX, vma->vm_end, ULONG_MAX, false);
trace_android_vh_swapmem_gather_finish(mm);
mmap_read_unlock(mm);
/*

View File

@@ -633,7 +633,7 @@ success:
* held in write mode.
*/
vma_start_write(vma);
vm_flags_reset(vma, vma_pad_fixup_flags(vma, newflags));
vm_flags_reset(vma, newflags);
/*
* We want to check manually if we can change individual PTEs writable
* if we can't do that automatically for all PTEs in a mapping. For

View File

@@ -53,6 +53,9 @@
#define CREATE_TRACE_POINTS
#include <trace/events/oom.h>
#undef CREATE_TRACE_POINTS
#include <trace/hooks/mm.h>
static int sysctl_panic_on_oom;
static int sysctl_oom_kill_allocating_task;
static int sysctl_oom_dump_tasks = 1;
@@ -525,6 +528,7 @@ bool __oom_reap_task_mm(struct mm_struct *mm)
*/
set_bit(MMF_UNSTABLE, &mm->flags);
trace_android_vh_oom_swapmem_gather_init(mm);
for_each_vma(vmi, vma) {
if (vma->vm_flags & (VM_HUGETLB|VM_PFNMAP))
continue;
@@ -557,6 +561,7 @@ bool __oom_reap_task_mm(struct mm_struct *mm)
tlb_finish_mmu(&tlb);
}
}
trace_android_vh_oom_swapmem_gather_finish(mm);
return ret;
}

View File

@@ -140,7 +140,7 @@ unsigned long vma_pad_pages(struct vm_area_struct *vma)
if (!is_pgsize_migration_enabled())
return 0;
return vma->vm_flags >> VM_PAD_SHIFT;
return (vma->vm_flags & VM_PAD_MASK) >> VM_PAD_SHIFT;
}
static __always_inline bool str_has_suffix(const char *str, const char *suffix)
@@ -413,8 +413,8 @@ void split_pad_vma(struct vm_area_struct *vma, struct vm_area_struct *new,
nr_vma2_pages = vma_pages(second);
if (nr_vma2_pages >= nr_pad_pages) { /* Case 1 & 3*/
vm_flags_clear(first, VM_PAD_MASK);
if (nr_vma2_pages >= nr_pad_pages) { /* Case 1 & 3 */
vma_set_pad_pages(first, 0);
vma_set_pad_pages(second, nr_pad_pages);
} else { /* Case 2 */
vma_set_pad_pages(first, nr_pad_pages - nr_vma2_pages);
@@ -422,18 +422,6 @@ void split_pad_vma(struct vm_area_struct *vma, struct vm_area_struct *new,
}
}
/*
* Sets the correct padding bits / flags for a VMA split.
*/
unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
unsigned long newflags)
{
if (newflags & VM_PAD_MASK)
return (newflags & ~VM_PAD_MASK) | (vma->vm_flags & VM_PAD_MASK);
else
return newflags;
}
/*
* Merging of padding VMAs is uncommon, as padding is only allowed
* from the linker context.

View File

@@ -994,7 +994,7 @@ static unsigned long shrink_slab_memcg(gfp_t gfp_mask, int nid,
*
* Returns the number of reclaimed slab objects.
*/
static unsigned long shrink_slab(gfp_t gfp_mask, int nid,
unsigned long shrink_slab(gfp_t gfp_mask, int nid,
struct mem_cgroup *memcg,
int priority)
{
@@ -1047,6 +1047,8 @@ out:
return freed;
}
EXPORT_SYMBOL_GPL(shrink_slab);
static void drop_slab_node(int nid)
{
unsigned long freed;
@@ -1478,6 +1480,10 @@ static enum folio_references folio_check_references(struct folio *folio,
int ret = 0;
bool trylock_failed = false;
#ifdef CONFIG_ANDROID_VENDOR_OEM_DATA
trace_android_vh_page_should_be_protected(folio, sc->nr_scanned,
sc->priority, &sc->android_vendor_data1, &ret);
#endif
trace_android_vh_check_folio_look_around_ref(folio, &ret);
if (ret)
return ret;
@@ -2647,6 +2653,8 @@ static void shrink_active_list(unsigned long nr_to_scan,
unsigned nr_rotated = 0;
int file = is_file_lru(lru);
struct pglist_data *pgdat = lruvec_pgdat(lruvec);
int should_protect = 0;
bool bypass = false;
lru_add_drain();
@@ -2683,6 +2691,19 @@ static void shrink_active_list(unsigned long nr_to_scan,
}
}
#ifdef CONFIG_ANDROID_VENDOR_OEM_DATA
trace_android_vh_page_should_be_protected(folio, sc->nr_scanned,
sc->priority, &sc->android_vendor_data1, &should_protect);
#endif
if (unlikely(should_protect)) {
nr_rotated += folio_nr_pages(folio);
list_add(&folio->lru, &l_active);
continue;
}
trace_android_vh_page_referenced_check_bypass(folio, nr_to_scan, lru, &bypass);
if (bypass)
goto skip_folio_referenced;
trace_android_vh_folio_trylock_set(folio);
/* Referenced or rmap lock contention: rotate */
if (folio_referenced(folio, 0, sc->target_mem_cgroup,
@@ -2704,6 +2725,7 @@ static void shrink_active_list(unsigned long nr_to_scan,
}
}
trace_android_vh_folio_trylock_clear(folio);
skip_folio_referenced:
folio_clear_active(folio); /* we are de-activating */
folio_set_workingset(folio);
list_add(&folio->lru, &l_inactive);

View File

@@ -927,6 +927,7 @@ out:
up_read(&devnet_rename_sem);
return ret;
}
EXPORT_SYMBOL_GPL(netdev_get_name);
/**
* dev_getbyhwaddr_rcu - find a device by its hardware address

View File

@@ -3487,6 +3487,7 @@ void tcp_send_active_reset(struct sock *sk, gfp_t priority)
*/
trace_tcp_send_reset(sk, NULL);
}
EXPORT_SYMBOL_GPL(tcp_send_active_reset);
/* Send a crossed SYN-ACK during socket establishment.
* WARNING: This routine must only be called when we have already sent

View File

@@ -437,12 +437,10 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
struct netem_sched_data *q = qdisc_priv(sch);
/* We don't fill cb now as skb_unshare() may invalidate it */
struct netem_skb_cb *cb;
struct sk_buff *skb2;
struct sk_buff *skb2 = NULL;
struct sk_buff *segs = NULL;
unsigned int prev_len = qdisc_pkt_len(skb);
int count = 1;
int rc = NET_XMIT_SUCCESS;
int rc_drop = NET_XMIT_DROP;
/* Do not fool qdisc_drop_all() */
skb->prev = NULL;
@@ -471,19 +469,11 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
skb_orphan_partial(skb);
/*
* If we need to duplicate packet, then re-insert at top of the
* qdisc tree, since parent queuer expects that only one
* skb will be queued.
* If we need to duplicate packet, then clone it before
* original is modified.
*/
if (count > 1 && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
struct Qdisc *rootq = qdisc_root_bh(sch);
u32 dupsave = q->duplicate; /* prevent duplicating a dup... */
q->duplicate = 0;
rootq->enqueue(skb2, rootq, to_free);
q->duplicate = dupsave;
rc_drop = NET_XMIT_SUCCESS;
}
if (count > 1)
skb2 = skb_clone(skb, GFP_ATOMIC);
/*
* Randomized packet corruption.
@@ -495,7 +485,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
if (skb_is_gso(skb)) {
skb = netem_segment(skb, sch, to_free);
if (!skb)
return rc_drop;
goto finish_segs;
segs = skb->next;
skb_mark_not_on_list(skb);
qdisc_skb_cb(skb)->pkt_len = skb->len;
@@ -521,7 +512,24 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
/* re-link segs, so that qdisc_drop_all() frees them all */
skb->next = segs;
qdisc_drop_all(skb, sch, to_free);
return rc_drop;
if (skb2)
__qdisc_drop(skb2, to_free);
return NET_XMIT_DROP;
}
/*
* If doing duplication then re-insert at top of the
* qdisc tree, since parent queuer expects that only one
* skb will be queued.
*/
if (skb2) {
struct Qdisc *rootq = qdisc_root_bh(sch);
u32 dupsave = q->duplicate; /* prevent duplicating a dup... */
q->duplicate = 0;
rootq->enqueue(skb2, rootq, to_free);
q->duplicate = dupsave;
skb2 = NULL;
}
qdisc_qstats_backlog_inc(sch, skb);
@@ -592,9 +600,12 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
}
finish_segs:
if (skb2)
__qdisc_drop(skb2, to_free);
if (segs) {
unsigned int len, last_len;
int nb;
int rc, nb;
len = skb ? skb->len : 0;
nb = skb ? 1 : 0;

View File

@@ -65,6 +65,7 @@ static int __do_binderfs_test(struct __test_metadata *_metadata)
static const char * const binder_features[] = {
"oneway_spam_detection",
"extended_error",
"freeze_notification",
};
change_mountns(_metadata);