mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 11:50:43 +09:00
Merge branch 'android13-5.10' into branch 'android13-5.10-lts'
Sync back up with changes in the android13-5.10 branch to catch the new symbols that we need to track properly.29c427664aMerge tag 'android13-5.10.149_r00' into android13-5.1070be865521ANDROID: Update the ABI representation57e680a1a8ANDROID: Sched: Add restricted vendor hook in update_misfit_status()64b7606115ANDROID: Sched: Add restricted vendor hook in schedule()ef815ee856ANDROID: Sched: Add restricted vendor hook in wake_up_new_task()b7dbea10b1ANDROID: Fix license for BUILD.bazel file.c45168c6c2ANDROID: kleaf: load() then package().2ff20aeeb6ANDROID: update the .xml ABI file due to LTS changes.887fa8f059Revert "mtd: fix 'part' field data corruption in mtd_info"e6a51ad94cRevert "audit: log AUDIT_TIME_* records only from rules"cac3a605c5Merge64f18041dd("Merge branch 'android13-5.10' into branch 'android13-5.10-lts'") into android13-5.10-ltscc59c47abbANDROID: GKI: rockchip: Enable symbols for charger and batteryfd1290ee6cANDROID: GKI: MGLRU ABI Fixupe0f24fb5c6ANDROID: GKI: Build multi-gen LRU92c47e2a15ANDROID: Make MGLRU aware of speculative faults9d5b3a1547BACKPORT: mm: multi-gen LRU: design docee101878a8UPSTREAM: mm: multi-gen LRU: admin guide86b889811dBACKPORT: mm: multi-gen LRU: debugfs interface3369bf02b2UPSTREAM: mm: multi-gen LRU: thrashing preventione9983679e7BACKPORT: mm: multi-gen LRU: kill switche4ed637282BACKPORT: mm: multi-gen LRU: optimize multiple memcgsc2869b6c22BACKPORT: mm: multi-gen LRU: support page table walksfd80133d8cBACKPORT: mm: multi-gen LRU: exploit locality in rmap8455e88fe4BACKPORT: mm: multi-gen LRU: minimal implementation278f56801aBACKPORT: mm: multi-gen LRU: groundwork245ea1de3eBACKPORT: mm/vmscan.c: refactor shrink_node()4ccde30ac9BACKPORT: mm: x86: add CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNGf04c2fbac2BACKPORT: mm: x86, arm64: add arch_has_hw_pte_young()691008625eRevert "FROMLIST: mm: x86, arm64: add arch_has_hw_pte_young()"4741bcbac4Revert "FROMLIST: mm: x86: add CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG"a38ef3be2bRevert "FROMLIST: mm/vmscan.c: refactor shrink_node()"ead7512d05Revert "FROMLIST: mm: multi-gen LRU: groundwork"b61dbc579bRevert "FROMLIST: mm: multi-gen LRU: minimal implementation"7a2929e68cRevert "FROMLIST: mm: multi-gen LRU: exploit locality in rmap"db1832bb7cRevert "FROMLIST: mm: multi-gen LRU: support page table walks"6fa2a68b43Revert "FROMLIST: mm: multi-gen LRU: optimize multiple memcgs"56c66e7cc4Revert "FROMLIST: mm: multi-gen LRU: kill switch"06e6006a04Revert "FROMLIST: mm: multi-gen LRU: thrashing prevention"0d9f7bf39cRevert "FROMLIST: mm: multi-gen LRU: debugfs interface"43c49618c8Revert "FROMLIST: mm: multi-gen LRU: admin guide"3676a0c29aRevert "FROMLIST: mm: multi-gen LRU: design doc"66f2c69836Revert "ANDROID: GKI: build multi-gen LRU"40dd81e34cRevert "ANDROID: Make MGLRU aware of speculative faults"baa23246e9UPSTREAM: binder: Gracefully handle BINDER_TYPE_FDA objects with num_fds=03d213a626dUPSTREAM: binder: Address corner cases in deferred copy and fixup9d1efccf5eUPSTREAM: binder: fix pointer cast warningb83173bf86UPSTREAM: binder: defer copies of pre-patched txn dataaaf2369717UPSTREAM: binder: read pre-translated fds from sender bufferecf61e4e11UPSTREAM: binder: avoid potential data leakage when copying txn3767674eacANDROID: khugepaged: fix mixing declarations warning in retract_page_tablesc440edc7a2ANDROID: mm: fix build issue in spf when CONFIG_USERFAULTFD=n2a62463d6eUPSTREAM: f2fs: don't use casefolded comparison for "." and ".."c63efa6751UPSTREAM: regulator: scmi: Fix refcount leak in scmi_regulator_probe9b8948cb0eUPSTREAM: KVM: arm64: vgic-v3: Consistently populate ID_AA64PFR0_EL1.GIC3bba44a8c3UPSTREAM: block/mq-deadline: Set the fifo_time member also if inserting at head49823ad276BACKPORT: Revert "mm/cma.c: remove redundant cma_mutex lock"fb3cba1815UPSTREAM: module.h: simplify MODULE_IMPORT_NS9257ade3bcUPSTREAM: procfs: prevent unprivileged processes accessing fdinfo dirae1f81f7f4UPSTREAM: KVM: arm64: nvhe: Eliminate kernel-doc warnings17d733d05bUPSTREAM: iommu/mediatek: Add mutex for m4u_group and m4u_dom in datab66bdceff1UPSTREAM: iommu/mediatek: Remove clk_disable in mtk_iommu_removec19e8027feUPSTREAM: iommu/mediatek: Fix 2 HW sharing pgtable issue80b363ae64UPSTREAM: mm: hugetlb: add missing cache flushing in hugetlb_unshare_all_pmds()4d39f905f5UPSTREAM: firmware: arm_ffa: Remove incorrect assignment of driver_datad57c415ab0UPSTREAM: firmware: arm_ffa: Fix uuid parameter to ffa_partition_probedba02a021aUPSTREAM: selftests/damon: add damon to selftests root Makefile9e059fe061BACKPORT: KVM: arm64: Actually prevent SMC64 SYSTEM_RESET2 from AArch32c6408580e1UPSTREAM: KVM: arm64: Generally disallow SMC64 for AArch32 guests1eed68cdc9UPSTREAM: irqchip/gic-v4: Wait for GICR_VPENDBASER.Dirty to clear before descheduling968c524dedUPSTREAM: virtio: use virtio_device_ready() in virtio_device_restore()9eaf45a22bUPSTREAM: mm: kfence: fix missing objcg housekeeping for SLAB7923c77f8fUPSTREAM: fs: erofs: add sanity check for kobject in erofs_unregister_sysfse7bbb89470UPSTREAM: clk: Fix clk_hw_get_clk() when dev is NULL69914efc9bUPSTREAM: arm64: kasan: fix include error in MTE functions2be9d2b296UPSTREAM: arm64: prevent instrumentation of bp hardening callbacks2917f48bdbUPSTREAM: PM: domains: Fix sleep-in-atomic bug caused by genpd_debug_remove()d9612d6109UPSTREAM: mm: fix use-after-free bug when mm->mmap is reused after being freed3b68c1140fUPSTREAM: kasan: test: prevent cache merging in kmem_cache_double_destroyd27c600b42BACKPORT: vsprintf: Fix %pK with kptr_restrict == 075a8a2c657ANDROID: KVM: arm64: Use 32-bit function ID for PSCI MEM_PROTECT call24ba7e97d3UPSTREAM: efi: capsule-loader: Fix use-after-free in efi_capsule_writed2426b0692UPSTREAM: net: preserve skb_end_offset() in skb_unclone_keeptruesize()2ea1a8c467BACKPORT: net: add skb_set_end_offset() helper7d40247c5bUPSTREAM: arm64: Correct wrong label in macro __init_el2_gicv3cb515c669cUPSTREAM: KVM: arm64: Stop handle_exit() from handling HVC twice when an SError occurs316b7560abUPSTREAM: KVM: arm64: Avoid consuming a stale esr value when SError occure3e5b3b856UPSTREAM: usb: typec: tcpm: Do not disconnect when receiving VSAFE0V2317bc5306UPSTREAM: usb: typec: tcpci: don't touch CC line if it's Vconn source8f2ac1deb1UPSTREAM: dt-bindings: memory: mtk-smi: Correct minItems to 2 for the gals clocks72decd9765BACKPORT: dt-bindings: memory: mtk-smi: No need mediatek,larb-id for mt816733e4819112BACKPORT: dt-bindings: memory: mtk-smi: Rename clock to clocks851451819eUPSTREAM: dma-buf: cma_heap: Fix mutex locking sectionc8f988d00dUPSTREAM: scsi: core: Declare 'scsi_scan_type' staticf3fe2dacb0UPSTREAM: scsi: core: Suppress a kernel-doc warning17b50edfadUPSTREAM: dma-buf: DMABUF_SYSFS_STATS should depend on DMA_SHARED_BUFFER4ececb4ebdUPSTREAM: clk: versatile: Depend on HAS_IOMEM9b70ff660fBACKPORT: arm64: meson: select COMMON_CLK05fbbf0d13UPSTREAM: tools: do not include scripts/Kbuild.include924872e549UPSTREAM: kbuild: dummy-tools: adjust to scripts/cc-version.sh252e42f395UPSTREAM: kbuild: do not include include/config/auto.conf from adjust_autoksyms.shb9a8323fdeUPSTREAM: scsi: docs: ABI: sysfs-driver-ufs: Add DeepSleep power mode26369cdee4ANDROID: gki_defconfig: enable CONFIG_USB_CONFIGFS_F_UVC0481654d9fANDROID: mm: disable speculative page faults for CONFIG_NUMAf6ddc1c41eANDROID: mm: fix invalid backport in speculative page fault pathc3f0fd7976ANDROID: disable page table moves when speculative page faults are enabled3d3b77c9c0ANDROID: mm: assert that mmap_lock is taken exclusively in vm_write_begindf62da3909ANDROID: mm: remove sequence counting when mmap_lock is not exclusively owned66544e79f4ANDROID: mm/khugepaged: add missing vm_write_{begin|end}2a3979df04BACKPORT: FROMLIST: mm: implement speculative handling in filemap_fault()ec35e912e7ANDROID: mm: prevent reads of unstable pmd during speculationce7fa7020aANDROID: mm: prevent speculative page fault handling for in do_swap_page()4812532eceANDROID: mm: prevent speculative page fault handling for userfaults43247cf563ANDROID: mm: skip pte_alloc during speculative page fault2f2dc42fbfANDROID: GKI: rockchip: Add symbols for cpufreqc8f45c4915ANDROID: Update the ABI representation0fabf2342fANDROID: sched: add hook point in do_sched_yield()2aed2a7cb0ANDROID: KVM: arm64: s2mpu: Fix SYNC latency regressione1ea4666e1ANDROID: KVM: arm64: iommu: Add host_stage2_idmap_complete15e65b4a22ANDROID: KVM: arm64: Issue CMOs when tearing down shadow pages80fcf382d1ANDROID: Add ashmem ioctl to return a unique file identifier056ee87d05ANDROID: Update the ABI representationb6cfd9d69fANDROID: KVM: arm64: Fix repainting of PSCI SYSTEM_RESET2 calls03b60942feANDROID: Update the ABI representationd08c3d3ba2ANDROID: Update the ABI representation01645da2f5ANDROID: Update the ABI representation6c86db3f70ANDROID: Update the ABI representationdb144888f8ANDROID: kernel: sched: Export reweight_task6f642cd2f2FROMGIT: f2fs: allow to read node block after shutdown92a7e867cfFROMGIT: usb: core: stop USB enumeration if too many retriesf3fe2e6612ANDROID: KVM: arm64: Adjust PSCI MEM_PROTECT refcount across share/unsharee7b635a520BACKPORT: ext4,f2fs: fix readahead of verity datac57ed31850ANDROID: Update the ABI representationbcf1e503f5ANDROID: adjust vendor hook to control blk_plug6cbaa88f4aANDROID: dm-user: Remove bio recount in I/O path69e2e9275bANDROID: Update the ABI representation501eeee6e2UPSTREAM: irqchip/tegra: Fix overflow implicit truncation warnings13a5e047bdUPSTREAM: drm/meson: Fix overflow implicit truncation warnings55a2910224UPSTREAM: video: fbdev: pxa3xx-gcu: Fix integer overflow in pxa3xx_gcu_write52e7aa3245FROMLIST: KVM: arm64: pkvm: Fixup boot mode to reflect that the kernel resumes from EL1bcb19fa296ANDROID: GKI: Add symbol list for exynos9e3ae1fbd3UPSTREAM: sched: Fix yet more sched_fork() races3de7d142cfBACKPORT: KVM: arm64: Fix bad dereference on MTE-enabled systemsb684150a44FROMLIST: binder: fix UAF of alloc->vma in race with munmap()9ffd177dceANDROID: Update the ABI representation89fed37332ANDROID: vendor hook to control blk_plug for shrink_lruvecc0ce22abf7UPSTREAM: mm: Fix TLB flush for not-first PFNMAP mappings in unmap_region()75c194cf1aUPSTREAM: af_key: Do not call xfrm_probe_algs in parallel8812ab3f9dUPSTREAM: mm: Force TLB flush for PFNMAP mappings before unlink_file_vma()4e97b7ff2bANDROID: KVM: arm64: Donate memory per vcpu for each vcpu shadow state6a7700c5b5ANDROID: KVM: arm64: Initialize shadow vcpus with separate hypercalls0b7f3b9652ANDROID: KVM: arm64: Refactor unpinning host vcpud345371dd2ANDROID: KVM: arm64: Separate functions for shadow vm and vcpu init66be6be8fbANDROID: KVM: arm64: Refactor code for reclaiming guest memory into a function232bdcbd66ANDROID: pass argument in zap_pte_range vendor hooksa83ef907f0ANDROID: GKI: Add for rockchip platform basic symbol05c1e5a6fdANDROID: GKI: Add Bazel rockchip symbol list entry56e639d3ffANDROID: sched: check on_rq in freezer_should_skip()90a47b6250ANDROID: Update the ABI representation14c8176992ANDROID: KVM: arm64: Only unpin a vCPU SVE state if set559e6700c3ANDROID: Update the ABI representation9966a706d1FROMGIT: f2fs: let's avoid to get cp_rwsem twice by f2fs_evict_inode by d_invalidate86d2835139ANDROID: Update the ABI representationa17e132ec4ANDROID: vendor hook to control blk_plug for memory reclaim1c741865f4ANDROID: Update the ABI representation6c543641c6UPSTREAM: wifi: mac80211: fix MBSSID parsing use-after-free187e6dad2aUPSTREAM: wifi: mac80211: don't parse mbssid in assoc response12bd079b61UPSTREAM: mac80211: mlme: find auth challenge directly13c3ed22feUPSTREAM: wifi: cfg80211: update hidden BSSes to avoid WARN_ON4bff45998eUPSTREAM: wifi: mac80211: fix crash in beacon protection for P2P-device7e9ccb517aUPSTREAM: wifi: mac80211_hwsim: avoid mac80211 warning on bad rate88b3da7668UPSTREAM: wifi: cfg80211: avoid nontransmitted BSS list corruption1e18328c84UPSTREAM: wifi: cfg80211: fix BSS refcounting bugsd56839bb09UPSTREAM: wifi: cfg80211: ensure length byte is present before accessd96c2b5944UPSTREAM: wifi: cfg80211/mac80211: reject bad MBSSID elements4ae8e2c20fUPSTREAM: wifi: cfg80211: fix u8 overflow in cfg80211_update_notlisted_nontrans()6e0df30312ANDROID: Update the ABI representation74e2ea264cANDROID: vendor hook to control bh_lru and lru_cache_disablef45d10e83bANDROID: Update the ABI representationd257ef6764ANDROID: vendor hook for TLB batching control2823b3889dUPSTREAM: fbcon: Prevent that screen size is smaller than font size739b963eb8UPSTREAM: fbcon: Disallow setting font bigger than screen sizecf3742cba4UPSTREAM: fbmem: Check virtual screen sizes in fb_set_var()788ba5e9deANDROID: GKI: Add build for rockchip platform90db4c38b9ANDROID: Update the ABI representation2f8253b7e6ANDROID: vendor hook to control pagevec flush992b5f98caANDROID: KVM: arm64: s2mpu: Add SysMMU_SYNC timeout19424168dbANDROID: KVM: arm64: Force CMOs with FWB when reclaiming guest pagesf177a280b1ANDROID: KVM: arm64: Fix MMIO guard map error handling32bef95f91UPSTREAM: psi: Fix psi state corruption when schedule() races with cgroup movee4c738dd13ANDROID: Update the ABI representation07e046b996BACKPORT: HID: steam: Prevent NULL pointer dereference in steam_{recv,send}_reportb366878684ANDROID: KVM: arm64: Fix MMIO guard unmapbefd3e393eUPSTREAM: crypto: jitter - add oversampling of noise source6ed90e9805ANDROID: Update the ABI representation9a8b45a9e4FROMGIT: f2fs: support recording stop_checkpoint reason into super_block .xml file updated with the abi preservation change: type 'struct sk_buff' changed member 'union { struct { __u8 scm_io_uring; __u8 android_kabi_reserved1_padding1; __u16 android_kabi_reserved1_padding2; __u32 android_kabi_reserved1_padding3; }; struct { u64 android_kabi_reserved1; }; union { }; }' was added member 'u64 android_kabi_reserved1' was removed Change-Id: I9ebc56503eafbab7e85a3d7dd6974beda91427ee Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
20
BUILD.bazel
20
BUILD.bazel
@@ -1,31 +1,23 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (C) 2021 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
load("//build/kernel/kleaf:common_kernels.bzl", "define_common_kernels")
|
||||
|
||||
package(
|
||||
default_visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
||||
|
||||
load("//build/kernel/kleaf:common_kernels.bzl", "define_common_kernels")
|
||||
|
||||
_aarch64_additional_kmi_symbol_lists = [
|
||||
# keep sorted
|
||||
"android/abi_gki_aarch64_core",
|
||||
"android/abi_gki_aarch64_db845c",
|
||||
"android/abi_gki_aarch64_exynos",
|
||||
"android/abi_gki_aarch64_fips140",
|
||||
"android/abi_gki_aarch64_generic",
|
||||
"android/abi_gki_aarch64_hikey960",
|
||||
"android/abi_gki_aarch64_rockchip",
|
||||
"android/abi_gki_aarch64_type_visibility",
|
||||
"android/abi_gki_aarch64_virtual_device",
|
||||
]
|
||||
|
||||
@@ -255,6 +255,17 @@ Description:
|
||||
is permitted, "u2" if only u2 is permitted, "u1_u2" if both u1 and
|
||||
u2 are permitted.
|
||||
|
||||
What: /sys/bus/usb/devices/.../<hub_interface>/port<X>/early_stop
|
||||
Date: Sep 2022
|
||||
Contact: Ray Chi <raychi@google.com>
|
||||
Description:
|
||||
Some USB hosts have some watchdog mechanisms so that the device
|
||||
may enter ramdump if it takes a long time during port initialization.
|
||||
This attribute allows each port just has two attempts so that the
|
||||
port initialization will be failed quickly. In addition, if a port
|
||||
which is marked with early_stop has failed to initialize, it will ignore
|
||||
all future connections until this attribute is clear.
|
||||
|
||||
What: /sys/bus/usb/devices/.../power/usb2_lpm_l1_timeout
|
||||
Date: May 2013
|
||||
Contact: Mathias Nyman <mathias.nyman@linux.intel.com>
|
||||
|
||||
@@ -916,21 +916,24 @@ Date: September 2014
|
||||
Contact: Subhash Jadavani <subhashj@codeaurora.org>
|
||||
Description: This entry could be used to set or show the UFS device
|
||||
runtime power management level. The current driver
|
||||
implementation supports 6 levels with next target states:
|
||||
implementation supports 7 levels with next target states:
|
||||
|
||||
== ====================================================
|
||||
0 an UFS device will stay active, an UIC link will
|
||||
0 UFS device will stay active, UIC link will
|
||||
stay active
|
||||
1 an UFS device will stay active, an UIC link will
|
||||
1 UFS device will stay active, UIC link will
|
||||
hibernate
|
||||
2 an UFS device will moved to sleep, an UIC link will
|
||||
2 UFS device will be moved to sleep, UIC link will
|
||||
stay active
|
||||
3 an UFS device will moved to sleep, an UIC link will
|
||||
3 UFS device will be moved to sleep, UIC link will
|
||||
hibernate
|
||||
4 an UFS device will be powered off, an UIC link will
|
||||
4 UFS device will be powered off, UIC link will
|
||||
hibernate
|
||||
5 an UFS device will be powered off, an UIC link will
|
||||
5 UFS device will be powered off, UIC link will
|
||||
be powered off
|
||||
6 UFS device will be moved to deep sleep, UIC link
|
||||
will be powered off. Note, deep sleep might not be
|
||||
supported in which case this value will not be accepted
|
||||
== ====================================================
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/rpm_target_dev_state
|
||||
@@ -954,21 +957,24 @@ Date: September 2014
|
||||
Contact: Subhash Jadavani <subhashj@codeaurora.org>
|
||||
Description: This entry could be used to set or show the UFS device
|
||||
system power management level. The current driver
|
||||
implementation supports 6 levels with next target states:
|
||||
implementation supports 7 levels with next target states:
|
||||
|
||||
== ====================================================
|
||||
0 an UFS device will stay active, an UIC link will
|
||||
0 UFS device will stay active, UIC link will
|
||||
stay active
|
||||
1 an UFS device will stay active, an UIC link will
|
||||
1 UFS device will stay active, UIC link will
|
||||
hibernate
|
||||
2 an UFS device will moved to sleep, an UIC link will
|
||||
2 UFS device will be moved to sleep, UIC link will
|
||||
stay active
|
||||
3 an UFS device will moved to sleep, an UIC link will
|
||||
3 UFS device will be moved to sleep, UIC link will
|
||||
hibernate
|
||||
4 an UFS device will be powered off, an UIC link will
|
||||
4 UFS device will be powered off, UIC link will
|
||||
hibernate
|
||||
5 an UFS device will be powered off, an UIC link will
|
||||
5 UFS device will be powered off, UIC link will
|
||||
be powered off
|
||||
6 UFS device will be moved to deep sleep, UIC link
|
||||
will be powered off. Note, deep sleep might not be
|
||||
supported in which case this value will not be accepted
|
||||
== ====================================================
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/spm_target_dev_state
|
||||
|
||||
@@ -3412,8 +3412,7 @@
|
||||
difficult since unequal pointers can no longer be
|
||||
compared. However, if this command-line option is
|
||||
specified, then all normal pointers will have their true
|
||||
value printed. Pointers printed via %pK may still be
|
||||
hashed. This option should only be specified when
|
||||
value printed. This option should only be specified when
|
||||
debugging the kernel. Please do not use on production
|
||||
kernels.
|
||||
|
||||
|
||||
@@ -24,12 +24,13 @@ following subsections.
|
||||
|
||||
Kill switch
|
||||
-----------
|
||||
``enable`` accepts different values to enable or disable the following
|
||||
components. Its default value depends on ``CONFIG_LRU_GEN_ENABLED``.
|
||||
All the components should be enabled unless some of them have
|
||||
unforeseen side effects. Writing to ``enable`` has no effect when a
|
||||
component is not supported by the hardware, and valid values will be
|
||||
accepted even when the main switch is off.
|
||||
``enabled`` accepts different values to enable or disable the
|
||||
following components. Its default value depends on
|
||||
``CONFIG_LRU_GEN_ENABLED``. All the components should be enabled
|
||||
unless some of them have unforeseen side effects. Writing to
|
||||
``enabled`` has no effect when a component is not supported by the
|
||||
hardware, and valid values will be accepted even when the main switch
|
||||
is off.
|
||||
|
||||
====== ===============================================================
|
||||
Values Components
|
||||
@@ -39,7 +40,9 @@ Values Components
|
||||
batches, when MMU sets it (e.g., on x86). This behavior can
|
||||
theoretically worsen lock contention (mmap_lock). If it is
|
||||
disabled, the multi-gen LRU will suffer a minor performance
|
||||
degradation.
|
||||
degradation for workloads that contiguously map hot pages,
|
||||
whose accessed bits can be otherwise cleared by fewer larger
|
||||
batches.
|
||||
0x0004 Clearing the accessed bit in non-leaf page table entries as
|
||||
well, when MMU sets it (e.g., on x86). This behavior was not
|
||||
verified on x86 varieties other than Intel and AMD. If it is
|
||||
@@ -90,18 +93,19 @@ evicted generations in this file.
|
||||
|
||||
Working set estimation
|
||||
----------------------
|
||||
Working set estimation measures how much memory an application
|
||||
requires in a given time interval, and it is usually done with little
|
||||
impact on the performance of the application. E.g., data centers want
|
||||
to optimize job scheduling (bin packing) to improve memory
|
||||
utilizations. When a new job comes in, the job scheduler needs to find
|
||||
out whether each server it manages can allocate a certain amount of
|
||||
memory for this new job before it can pick a candidate. To do so, this
|
||||
job scheduler needs to estimate the working sets of the existing jobs.
|
||||
Working set estimation measures how much memory an application needs
|
||||
in a given time interval, and it is usually done with little impact on
|
||||
the performance of the application. E.g., data centers want to
|
||||
optimize job scheduling (bin packing) to improve memory utilizations.
|
||||
When a new job comes in, the job scheduler needs to find out whether
|
||||
each server it manages can allocate a certain amount of memory for
|
||||
this new job before it can pick a candidate. To do so, the job
|
||||
scheduler needs to estimate the working sets of the existing jobs.
|
||||
|
||||
When it is read, ``lru_gen`` returns a histogram of numbers of pages
|
||||
accessed over different time intervals for each memcg and node.
|
||||
``MAX_NR_GENS`` decides the number of bins for each histogram.
|
||||
``MAX_NR_GENS`` decides the number of bins for each histogram. The
|
||||
histograms are noncumulative.
|
||||
::
|
||||
|
||||
memcg memcg_id memcg_path
|
||||
@@ -110,43 +114,49 @@ accessed over different time intervals for each memcg and node.
|
||||
...
|
||||
max_gen_nr age_in_ms nr_anon_pages nr_file_pages
|
||||
|
||||
Each generation contains an estimated number of pages that have been
|
||||
accessed within ``age_in_ms`` non-cumulatively. E.g., ``min_gen_nr``
|
||||
contains the coldest pages and ``max_gen_nr`` contains the hottest
|
||||
pages, since ``age_in_ms`` of the former is the largest and that of
|
||||
the latter is the smallest.
|
||||
Each bin contains an estimated number of pages that have been accessed
|
||||
within ``age_in_ms``. E.g., ``min_gen_nr`` contains the coldest pages
|
||||
and ``max_gen_nr`` contains the hottest pages, since ``age_in_ms`` of
|
||||
the former is the largest and that of the latter is the smallest.
|
||||
|
||||
Users can write ``+ memcg_id node_id max_gen_nr
|
||||
[can_swap[full_scan]]`` to ``lru_gen`` to create a new generation
|
||||
``max_gen_nr+1``. ``can_swap`` defaults to the swap setting and, if it
|
||||
is set to ``1``, it forces the scan of anon pages when swap is off.
|
||||
``full_scan`` defaults to ``1`` and, if it is set to ``0``, it reduces
|
||||
the overhead as well as the coverage when scanning page tables.
|
||||
Users can write the following command to ``lru_gen`` to create a new
|
||||
generation ``max_gen_nr+1``:
|
||||
|
||||
A typical use case is that a job scheduler writes to ``lru_gen`` at a
|
||||
``+ memcg_id node_id max_gen_nr [can_swap [force_scan]]``
|
||||
|
||||
``can_swap`` defaults to the swap setting and, if it is set to ``1``,
|
||||
it forces the scan of anon pages when swap is off, and vice versa.
|
||||
``force_scan`` defaults to ``1`` and, if it is set to ``0``, it
|
||||
employs heuristics to reduce the overhead, which is likely to reduce
|
||||
the coverage as well.
|
||||
|
||||
A typical use case is that a job scheduler runs this command at a
|
||||
certain time interval to create new generations, and it ranks the
|
||||
servers it manages based on the sizes of their cold memory defined by
|
||||
servers it manages based on the sizes of their cold pages defined by
|
||||
this time interval.
|
||||
|
||||
Proactive reclaim
|
||||
-----------------
|
||||
Proactive reclaim induces memory reclaim when there is no memory
|
||||
pressure and usually targets cold memory only. E.g., when a new job
|
||||
comes in, the job scheduler wants to proactively reclaim memory on the
|
||||
server it has selected to improve the chance of successfully landing
|
||||
Proactive reclaim induces page reclaim when there is no memory
|
||||
pressure. It usually targets cold pages only. E.g., when a new job
|
||||
comes in, the job scheduler wants to proactively reclaim cold pages on
|
||||
the server it selected, to improve the chance of successfully landing
|
||||
this new job.
|
||||
|
||||
Users can write ``- memcg_id node_id min_gen_nr [swappiness
|
||||
[nr_to_reclaim]]`` to ``lru_gen`` to evict generations less than or
|
||||
equal to ``min_gen_nr``. Note that ``min_gen_nr`` should be less than
|
||||
``max_gen_nr-1`` as ``max_gen_nr`` and ``max_gen_nr-1`` are not fully
|
||||
aged and therefore cannot be evicted. ``swappiness`` overrides the
|
||||
default value in ``/proc/sys/vm/swappiness``. ``nr_to_reclaim`` limits
|
||||
the number of pages to evict.
|
||||
Users can write the following command to ``lru_gen`` to evict
|
||||
generations less than or equal to ``min_gen_nr``.
|
||||
|
||||
A typical use case is that a job scheduler writes to ``lru_gen``
|
||||
before it tries to land a new job on a server, and if it fails to
|
||||
materialize the cold memory without impacting the existing jobs on
|
||||
this server, it retries on the next server according to the ranking
|
||||
result obtained from the working set estimation step described
|
||||
earlier.
|
||||
``- memcg_id node_id min_gen_nr [swappiness [nr_to_reclaim]]``
|
||||
|
||||
``min_gen_nr`` should be less than ``max_gen_nr-1``, since
|
||||
``max_gen_nr`` and ``max_gen_nr-1`` are not fully aged (equivalent to
|
||||
the active list) and therefore cannot be evicted. ``swappiness``
|
||||
overrides the default value in ``/proc/sys/vm/swappiness``.
|
||||
``nr_to_reclaim`` limits the number of pages to evict.
|
||||
|
||||
A typical use case is that a job scheduler runs this command before it
|
||||
tries to land a new job on a server. If it fails to materialize enough
|
||||
cold pages because of the overestimation, it retries on the next
|
||||
server according to the ranking result obtained from the working set
|
||||
estimation step. This less forceful approach limits the impacts on the
|
||||
existing jobs.
|
||||
|
||||
@@ -82,10 +82,9 @@ allOf:
|
||||
- mediatek,mt2701-smi-common
|
||||
then:
|
||||
properties:
|
||||
clock:
|
||||
items:
|
||||
minItems: 3
|
||||
maxItems: 3
|
||||
clocks:
|
||||
minItems: 3
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
- const: apb
|
||||
@@ -101,10 +100,9 @@ allOf:
|
||||
|
||||
then:
|
||||
properties:
|
||||
clock:
|
||||
items:
|
||||
minItems: 4
|
||||
maxItems: 4
|
||||
clocks:
|
||||
minItems: 4
|
||||
maxItems: 4
|
||||
clock-names:
|
||||
items:
|
||||
- const: apb
|
||||
@@ -114,10 +112,9 @@ allOf:
|
||||
|
||||
else: # for gen2 HW that don't have gals
|
||||
properties:
|
||||
clock:
|
||||
items:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
clocks:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
clock-names:
|
||||
items:
|
||||
- const: apb
|
||||
|
||||
@@ -77,11 +77,11 @@ allOf:
|
||||
|
||||
then:
|
||||
properties:
|
||||
clock:
|
||||
items:
|
||||
minItems: 3
|
||||
maxItems: 3
|
||||
clocks:
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
minItems: 2
|
||||
items:
|
||||
- const: apb
|
||||
- const: smi
|
||||
@@ -89,10 +89,9 @@ allOf:
|
||||
|
||||
else:
|
||||
properties:
|
||||
clock:
|
||||
items:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
clocks:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
clock-names:
|
||||
items:
|
||||
- const: apb
|
||||
@@ -106,7 +105,6 @@ allOf:
|
||||
- mediatek,mt2701-smi-larb
|
||||
- mediatek,mt2712-smi-larb
|
||||
- mediatek,mt6779-smi-larb
|
||||
- mediatek,mt8167-smi-larb
|
||||
|
||||
then:
|
||||
required:
|
||||
|
||||
@@ -22,15 +22,15 @@ The design objectives are:
|
||||
The representation of access recency is at the core of all LRU
|
||||
implementations. In the multi-gen LRU, each generation represents a
|
||||
group of pages with similar access recency. Generations establish a
|
||||
common frame of reference and therefore help make better choices,
|
||||
e.g., between different memcgs on a computer or different computers in
|
||||
a data center (for job scheduling).
|
||||
(time-based) common frame of reference and therefore help make better
|
||||
choices, e.g., between different memcgs on a computer or different
|
||||
computers in a data center (for job scheduling).
|
||||
|
||||
Exploiting spatial locality improves efficiency when gathering the
|
||||
accessed bit. A rmap walk targets a single page and does not try to
|
||||
profit from discovering a young PTE. A page table walk can sweep all
|
||||
the young PTEs in an address space, but the address space can be too
|
||||
large to make a profit. The key is to optimize both methods and use
|
||||
sparse to make a profit. The key is to optimize both methods and use
|
||||
them in combination.
|
||||
|
||||
Fast paths reduce code complexity and runtime overhead. Unmapped pages
|
||||
@@ -38,7 +38,7 @@ do not require TLB flushes; clean pages do not require writeback.
|
||||
These facts are only helpful when other conditions, e.g., access
|
||||
recency, are similar. With generations as a common frame of reference,
|
||||
additional factors stand out. But obvious choices might not be good
|
||||
choices; thus self-correction is required.
|
||||
choices; thus self-correction is necessary.
|
||||
|
||||
The benefits of simple self-correcting heuristics are self-evident.
|
||||
Again, with generations as a common frame of reference, this becomes
|
||||
@@ -64,7 +64,7 @@ The protection of the former channel is by design stronger because:
|
||||
3. The penalty of underprotecting the former channel is higher because
|
||||
applications usually do not prepare themselves for major page
|
||||
faults like they do for blocked I/O. E.g., GUI applications
|
||||
commonly use dedicated I/O threads to avoid blocking the rendering
|
||||
commonly use dedicated I/O threads to avoid blocking rendering
|
||||
threads.
|
||||
|
||||
There are also two access patterns:
|
||||
@@ -88,19 +88,19 @@ pages can be evicted regardless of swap constraints. These three
|
||||
variables are monotonically increasing.
|
||||
|
||||
Generation numbers are truncated into ``order_base_2(MAX_NR_GENS+1)``
|
||||
bits in order to fit into the gen counter in ``page->flags``. Each
|
||||
bits in order to fit into the gen counter in ``folio->flags``. Each
|
||||
truncated generation number is an index to ``lrugen->lists[]``. The
|
||||
sliding window technique is used to track at least ``MIN_NR_GENS`` and
|
||||
at most ``MAX_NR_GENS`` generations. The gen counter stores a value
|
||||
within ``[1, MAX_NR_GENS]`` while a page is on one of
|
||||
``lrugen->lists[]``; otherwise it stores zero.
|
||||
|
||||
Each generation is divided into multiple tiers. Tiers represent
|
||||
different ranges of numbers of accesses through file descriptors. A
|
||||
page accessed ``N`` times through file descriptors is in tier
|
||||
``order_base_2(N)``. In contrast to moving across generations, which
|
||||
requires the LRU lock, moving across tiers only requires operations on
|
||||
``page->flags`` and therefore has a negligible cost. A feedback loop
|
||||
Each generation is divided into multiple tiers. A page accessed ``N``
|
||||
times through file descriptors is in tier ``order_base_2(N)``. Unlike
|
||||
generations, tiers do not have dedicated ``lrugen->lists[]``. In
|
||||
contrast to moving across generations, which requires the LRU lock,
|
||||
moving across tiers only involves atomic operations on
|
||||
``folio->flags`` and therefore has a negligible cost. A feedback loop
|
||||
modeled after the PID controller monitors refaults over all the tiers
|
||||
from anon and file types and decides which tiers from which types to
|
||||
evict or protect.
|
||||
@@ -118,12 +118,11 @@ demotion of cold pages happens consequently when it increments
|
||||
``max_seq``. The aging uses page table walks and rmap walks to find
|
||||
young PTEs. For the former, it iterates ``lruvec_memcg()->mm_list``
|
||||
and calls ``walk_page_range()`` with each ``mm_struct`` on this list
|
||||
to scan PTEs. On finding a young PTE, it clears the accessed bit and
|
||||
updates the gen counter of the page mapped by this PTE to
|
||||
``(max_seq%MAX_NR_GENS)+1``. After each iteration of this list, it
|
||||
increments ``max_seq``. For the latter, when the eviction walks the
|
||||
rmap and finds a young PTE, the aging scans the adjacent PTEs and
|
||||
follows the same steps just described.
|
||||
to scan PTEs, and after each iteration, it increments ``max_seq``. For
|
||||
the latter, when the eviction walks the rmap and finds a young PTE,
|
||||
the aging scans the adjacent PTEs. For both, on finding a young PTE,
|
||||
the aging clears the accessed bit and updates the gen counter of the
|
||||
page mapped by this PTE to ``(max_seq%MAX_NR_GENS)+1``.
|
||||
|
||||
Eviction
|
||||
--------
|
||||
@@ -134,12 +133,12 @@ evict from, it first compares ``min_seq[]`` to select the older type.
|
||||
If both types are equally old, it selects the one whose first tier has
|
||||
a lower refault percentage. The first tier contains single-use
|
||||
unmapped clean pages, which are the best bet. The eviction sorts a
|
||||
page according to the gen counter if the aging has found this page
|
||||
accessed through page tables and updated the gen counter. It also
|
||||
page according to its gen counter if the aging has found this page
|
||||
accessed through page tables and updated its gen counter. It also
|
||||
moves a page to the next generation, i.e., ``min_seq+1``, if this page
|
||||
was accessed multiple times through file descriptors and the feedback
|
||||
loop has detected outlying refaults from the tier this page is in. To
|
||||
do this, the feedback loop uses the first tier as the baseline, for
|
||||
this end, the feedback loop uses the first tier as the baseline, for
|
||||
the reason stated earlier.
|
||||
|
||||
Summary
|
||||
@@ -147,14 +146,14 @@ Summary
|
||||
The multi-gen LRU can be disassembled into the following parts:
|
||||
|
||||
* Generations
|
||||
* Page table walks
|
||||
* Rmap walks
|
||||
* Page table walks
|
||||
* Bloom filters
|
||||
* The PID controller
|
||||
* PID controller
|
||||
|
||||
The aging and the eviction is a producer-consumer model; specifically,
|
||||
the latter drives the former by the sliding window over generations.
|
||||
Within the aging, rmap walks drive page table walks by inserting hot
|
||||
densely populated page tables to the Bloom filters. Within the
|
||||
eviction, the PID controller uses refaults as the feedback to select
|
||||
types to evict and tiers to protect.
|
||||
The aging and the eviction form a producer-consumer model;
|
||||
specifically, the latter drives the former by the sliding window over
|
||||
generations. Within the aging, rmap walks drive page table walks by
|
||||
inserting hot densely populated page tables to the Bloom filters.
|
||||
Within the eviction, the PID controller uses refaults as the feedback
|
||||
to select types to evict and tiers to protect.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1842
android/abi_gki_aarch64_exynos
Normal file
1842
android/abi_gki_aarch64_exynos
Normal file
File diff suppressed because it is too large
Load Diff
@@ -111,6 +111,7 @@
|
||||
_raw_spin_lock
|
||||
_raw_spin_unlock
|
||||
refcount_warn_saturate
|
||||
rng_is_initialized
|
||||
scatterwalk_ffwd
|
||||
scatterwalk_map_and_copy
|
||||
sg_init_one
|
||||
|
||||
@@ -189,6 +189,7 @@
|
||||
cfg80211_vendor_cmd_reply
|
||||
__cfi_slowpath
|
||||
__check_object_size
|
||||
check_preempt_curr
|
||||
__class_create
|
||||
class_destroy
|
||||
class_interface_unregister
|
||||
@@ -993,8 +994,12 @@
|
||||
hid_allocate_device
|
||||
hid_debug
|
||||
hid_destroy_device
|
||||
hid_hw_start
|
||||
hid_input_report
|
||||
hid_open_report
|
||||
hid_parse_report
|
||||
__hid_register_driver
|
||||
hid_unregister_driver
|
||||
hrtimer_active
|
||||
hrtimer_cancel
|
||||
hrtimer_forward
|
||||
@@ -1800,9 +1805,11 @@
|
||||
__request_percpu_irq
|
||||
__request_region
|
||||
request_threaded_irq
|
||||
resched_curr
|
||||
resume_cpus
|
||||
return_address
|
||||
revalidate_disk_size
|
||||
reweight_task
|
||||
rfkill_alloc
|
||||
rfkill_destroy
|
||||
rfkill_init_sw_state
|
||||
@@ -2219,12 +2226,15 @@
|
||||
__traceiter_android_rvh_post_init_entity_util_avg
|
||||
__traceiter_android_rvh_preempt_disable
|
||||
__traceiter_android_rvh_preempt_enable
|
||||
__traceiter_android_rvh_prepare_prio_fork
|
||||
__traceiter_android_rvh_remove_entity_load_avg
|
||||
__traceiter_android_rvh_sched_fork
|
||||
__traceiter_android_rvh_select_task_rq_fair
|
||||
__traceiter_android_rvh_select_task_rq_rt
|
||||
__traceiter_android_rvh_set_iowait
|
||||
__traceiter_android_rvh_setscheduler
|
||||
__traceiter_android_rvh_set_task_cpu
|
||||
__traceiter_android_rvh_set_user_nice
|
||||
__traceiter_android_rvh_typec_tcpci_chk_contaminant
|
||||
__traceiter_android_rvh_typec_tcpci_get_vbus
|
||||
__traceiter_android_rvh_uclamp_eff_get
|
||||
@@ -2237,11 +2247,15 @@
|
||||
__traceiter_android_rvh_update_rt_rq_load_avg
|
||||
__traceiter_android_rvh_util_est_update
|
||||
__traceiter_android_vh_arch_set_freq_scale
|
||||
__traceiter_android_vh_bh_lru_install
|
||||
__traceiter_android_vh_binder_restore_priority
|
||||
__traceiter_android_vh_binder_set_priority
|
||||
__traceiter_android_vh_cma_alloc_adjust
|
||||
__traceiter_android_vh_cma_alloc_finish
|
||||
__traceiter_android_vh_cma_alloc_start
|
||||
__traceiter_android_vh_cpu_idle_enter
|
||||
__traceiter_android_vh_cpu_idle_exit
|
||||
__traceiter_android_vh_do_madvise_blk_plug
|
||||
__traceiter_android_vh_dump_throttled_rt_tasks
|
||||
__traceiter_android_vh_dup_task_struct
|
||||
__traceiter_android_vh_early_resume_begin
|
||||
@@ -2256,13 +2270,19 @@
|
||||
__traceiter_android_vh_mm_compaction_end
|
||||
__traceiter_android_vh_of_i2c_get_board_info
|
||||
__traceiter_android_vh_pagecache_get_page
|
||||
__traceiter_android_vh_pagevec_drain
|
||||
__traceiter_android_vh_pin_user_pages
|
||||
__traceiter_android_vh_rebuild_root_domains_bypass
|
||||
__traceiter_android_vh_reclaim_pages_plug
|
||||
__traceiter_android_vh_resume_end
|
||||
__traceiter_android_vh_rmqueue
|
||||
__traceiter_android_vh_sched_setaffinity_early
|
||||
__traceiter_android_vh_scheduler_tick
|
||||
__traceiter_android_vh_setscheduler_uclamp
|
||||
__traceiter_android_vh_show_max_freq
|
||||
__traceiter_android_vh_shrink_inactive_list_blk_plug
|
||||
__traceiter_android_vh_shrink_lruvec_blk_plug
|
||||
__traceiter_android_vh_skip_lru_disable
|
||||
__traceiter_android_vh_snd_compr_use_pause_in_drain
|
||||
__traceiter_android_vh_sound_usb_support_cpu_suspend
|
||||
__traceiter_android_vh_sysrq_crash
|
||||
@@ -2286,6 +2306,9 @@
|
||||
__traceiter_android_vh_ufs_update_sysfs
|
||||
__traceiter_android_vh_usb_dev_resume
|
||||
__traceiter_android_vh_usb_dev_suspend
|
||||
__traceiter_android_vh_zap_pte_range_tlb_end
|
||||
__traceiter_android_vh_zap_pte_range_tlb_force_flush
|
||||
__traceiter_android_vh_zap_pte_range_tlb_start
|
||||
__traceiter_clock_set_rate
|
||||
__traceiter_cpu_frequency
|
||||
__traceiter_device_pm_callback_end
|
||||
@@ -2293,6 +2316,8 @@
|
||||
__traceiter_dwc3_readl
|
||||
__traceiter_dwc3_writel
|
||||
__traceiter_gpu_mem_total
|
||||
__traceiter_irq_handler_entry
|
||||
__traceiter_irq_handler_exit
|
||||
__traceiter_mm_vmscan_direct_reclaim_begin
|
||||
__traceiter_mm_vmscan_direct_reclaim_end
|
||||
__traceiter_pelt_cfs_tp
|
||||
@@ -2308,6 +2333,8 @@
|
||||
__traceiter_sched_switch
|
||||
__traceiter_sched_util_est_cfs_tp
|
||||
__traceiter_sched_util_est_se_tp
|
||||
__traceiter_softirq_entry
|
||||
__traceiter_softirq_exit
|
||||
__traceiter_suspend_resume
|
||||
trace_output_call
|
||||
__tracepoint_android_rvh_arm64_serror_panic
|
||||
@@ -2335,12 +2362,15 @@
|
||||
__tracepoint_android_rvh_post_init_entity_util_avg
|
||||
__tracepoint_android_rvh_preempt_disable
|
||||
__tracepoint_android_rvh_preempt_enable
|
||||
__tracepoint_android_rvh_prepare_prio_fork
|
||||
__tracepoint_android_rvh_remove_entity_load_avg
|
||||
__tracepoint_android_rvh_sched_fork
|
||||
__tracepoint_android_rvh_select_task_rq_fair
|
||||
__tracepoint_android_rvh_select_task_rq_rt
|
||||
__tracepoint_android_rvh_set_iowait
|
||||
__tracepoint_android_rvh_setscheduler
|
||||
__tracepoint_android_rvh_set_task_cpu
|
||||
__tracepoint_android_rvh_set_user_nice
|
||||
__tracepoint_android_rvh_typec_tcpci_chk_contaminant
|
||||
__tracepoint_android_rvh_typec_tcpci_get_vbus
|
||||
__tracepoint_android_rvh_uclamp_eff_get
|
||||
@@ -2353,11 +2383,15 @@
|
||||
__tracepoint_android_rvh_update_rt_rq_load_avg
|
||||
__tracepoint_android_rvh_util_est_update
|
||||
__tracepoint_android_vh_arch_set_freq_scale
|
||||
__tracepoint_android_vh_bh_lru_install
|
||||
__tracepoint_android_vh_binder_restore_priority
|
||||
__tracepoint_android_vh_binder_set_priority
|
||||
__tracepoint_android_vh_cma_alloc_adjust
|
||||
__tracepoint_android_vh_cma_alloc_finish
|
||||
__tracepoint_android_vh_cma_alloc_start
|
||||
__tracepoint_android_vh_cpu_idle_enter
|
||||
__tracepoint_android_vh_cpu_idle_exit
|
||||
__tracepoint_android_vh_do_madvise_blk_plug
|
||||
__tracepoint_android_vh_dump_throttled_rt_tasks
|
||||
__tracepoint_android_vh_dup_task_struct
|
||||
__tracepoint_android_vh_early_resume_begin
|
||||
@@ -2372,13 +2406,19 @@
|
||||
__tracepoint_android_vh_mm_compaction_end
|
||||
__tracepoint_android_vh_of_i2c_get_board_info
|
||||
__tracepoint_android_vh_pagecache_get_page
|
||||
__tracepoint_android_vh_pagevec_drain
|
||||
__tracepoint_android_vh_pin_user_pages
|
||||
__tracepoint_android_vh_rebuild_root_domains_bypass
|
||||
__tracepoint_android_vh_reclaim_pages_plug
|
||||
__tracepoint_android_vh_resume_end
|
||||
__tracepoint_android_vh_rmqueue
|
||||
__tracepoint_android_vh_sched_setaffinity_early
|
||||
__tracepoint_android_vh_scheduler_tick
|
||||
__tracepoint_android_vh_setscheduler_uclamp
|
||||
__tracepoint_android_vh_show_max_freq
|
||||
__tracepoint_android_vh_shrink_inactive_list_blk_plug
|
||||
__tracepoint_android_vh_shrink_lruvec_blk_plug
|
||||
__tracepoint_android_vh_skip_lru_disable
|
||||
__tracepoint_android_vh_snd_compr_use_pause_in_drain
|
||||
__tracepoint_android_vh_sound_usb_support_cpu_suspend
|
||||
__tracepoint_android_vh_sysrq_crash
|
||||
@@ -2402,6 +2442,9 @@
|
||||
__tracepoint_android_vh_ufs_update_sysfs
|
||||
__tracepoint_android_vh_usb_dev_resume
|
||||
__tracepoint_android_vh_usb_dev_suspend
|
||||
__tracepoint_android_vh_zap_pte_range_tlb_end
|
||||
__tracepoint_android_vh_zap_pte_range_tlb_force_flush
|
||||
__tracepoint_android_vh_zap_pte_range_tlb_start
|
||||
__tracepoint_clock_set_rate
|
||||
__tracepoint_cpu_frequency
|
||||
__tracepoint_device_pm_callback_end
|
||||
@@ -2409,6 +2452,8 @@
|
||||
__tracepoint_dwc3_readl
|
||||
__tracepoint_dwc3_writel
|
||||
__tracepoint_gpu_mem_total
|
||||
__tracepoint_irq_handler_entry
|
||||
__tracepoint_irq_handler_exit
|
||||
__tracepoint_mm_vmscan_direct_reclaim_begin
|
||||
__tracepoint_mm_vmscan_direct_reclaim_end
|
||||
__tracepoint_pelt_cfs_tp
|
||||
@@ -2426,6 +2471,8 @@
|
||||
__tracepoint_sched_switch
|
||||
__tracepoint_sched_util_est_cfs_tp
|
||||
__tracepoint_sched_util_est_se_tp
|
||||
__tracepoint_softirq_entry
|
||||
__tracepoint_softirq_exit
|
||||
__tracepoint_suspend_resume
|
||||
trace_print_array_seq
|
||||
trace_print_bitmask_seq
|
||||
|
||||
536
android/abi_gki_aarch64_rockchip
Normal file
536
android/abi_gki_aarch64_rockchip
Normal file
@@ -0,0 +1,536 @@
|
||||
[abi_symbol_list]
|
||||
# commonly used symbols
|
||||
alloc_workqueue
|
||||
arm64_const_caps_ready
|
||||
atomic_notifier_chain_register
|
||||
atomic_notifier_chain_unregister
|
||||
cancel_delayed_work_sync
|
||||
__cfi_slowpath
|
||||
clk_bulk_disable
|
||||
clk_bulk_enable
|
||||
clk_bulk_prepare
|
||||
clk_bulk_unprepare
|
||||
clk_disable
|
||||
clk_enable
|
||||
clk_gate_ops
|
||||
clk_get
|
||||
__clk_get_name
|
||||
clk_get_rate
|
||||
clk_notifier_register
|
||||
clk_prepare
|
||||
clk_put
|
||||
clk_register
|
||||
clk_set_rate
|
||||
clk_unprepare
|
||||
__const_udelay
|
||||
__cpufreq_driver_target
|
||||
cpufreq_generic_suspend
|
||||
cpufreq_register_governor
|
||||
cpufreq_register_notifier
|
||||
cpufreq_unregister_governor
|
||||
cpu_hwcap_keys
|
||||
cpu_latency_qos_add_request
|
||||
cpu_latency_qos_update_request
|
||||
cpumask_next
|
||||
cpu_number
|
||||
__cpu_online_mask
|
||||
__cpu_possible_mask
|
||||
cpus_read_lock
|
||||
cpus_read_unlock
|
||||
delayed_work_timer_fn
|
||||
_dev_err
|
||||
devfreq_recommended_opp
|
||||
dev_fwnode
|
||||
device_create_file
|
||||
device_init_wakeup
|
||||
device_property_present
|
||||
device_property_read_u32_array
|
||||
device_property_read_u8_array
|
||||
_dev_info
|
||||
devm_clk_bulk_get_all
|
||||
devm_clk_get
|
||||
devm_clk_hw_register
|
||||
devm_clk_register
|
||||
devm_gpiod_get_optional
|
||||
devm_ioremap_resource
|
||||
devm_kfree
|
||||
devm_kmalloc
|
||||
devm_nvmem_register
|
||||
devm_platform_ioremap_resource
|
||||
devm_power_supply_register
|
||||
devm_regmap_field_alloc
|
||||
__devm_regmap_init_i2c
|
||||
devm_regulator_get
|
||||
devm_regulator_get_optional
|
||||
devm_regulator_register
|
||||
devm_request_threaded_irq
|
||||
devm_reset_control_array_get
|
||||
dev_pm_opp_find_freq_ceil
|
||||
dev_pm_opp_get_opp_count
|
||||
dev_pm_opp_get_opp_table
|
||||
dev_pm_opp_get_voltage
|
||||
dev_pm_opp_of_get_sharing_cpus
|
||||
dev_pm_opp_put
|
||||
dev_pm_opp_put_opp_table
|
||||
dev_pm_opp_put_regulators
|
||||
dev_pm_opp_register_set_opp_helper
|
||||
dev_pm_opp_set_rate
|
||||
dev_pm_opp_set_regulators
|
||||
devres_add
|
||||
devres_alloc_node
|
||||
devres_free
|
||||
_dev_warn
|
||||
down_read
|
||||
down_write
|
||||
freq_qos_add_request
|
||||
freq_qos_remove_request
|
||||
freq_qos_update_request
|
||||
get_cpu_device
|
||||
gpiod_direction_output
|
||||
gpiod_get_value
|
||||
i2c_del_driver
|
||||
i2c_register_driver
|
||||
i2c_smbus_read_i2c_block_data
|
||||
i2c_smbus_write_i2c_block_data
|
||||
init_timer_key
|
||||
iounmap
|
||||
irq_set_irq_wake
|
||||
irq_to_desc
|
||||
kfree
|
||||
__kmalloc
|
||||
kmalloc_caches
|
||||
kmem_cache_alloc_trace
|
||||
ktime_get
|
||||
__list_add_valid
|
||||
__list_del_entry_valid
|
||||
__log_post_read_mmio
|
||||
__log_read_mmio
|
||||
__log_write_mmio
|
||||
memcpy
|
||||
memset
|
||||
module_layout
|
||||
__msecs_to_jiffies
|
||||
msleep
|
||||
__mutex_init
|
||||
mutex_lock
|
||||
mutex_unlock
|
||||
nr_cpu_ids
|
||||
nvmem_cell_put
|
||||
nvmem_cell_read
|
||||
of_clk_add_provider
|
||||
of_clk_del_provider
|
||||
of_clk_get
|
||||
of_clk_get_by_name
|
||||
of_clk_get_parent_count
|
||||
of_clk_src_simple_get
|
||||
of_count_phandle_with_args
|
||||
of_device_get_match_data
|
||||
of_device_is_available
|
||||
of_device_is_compatible
|
||||
of_find_matching_node_and_match
|
||||
of_find_node_by_name
|
||||
of_find_property
|
||||
of_get_child_by_name
|
||||
of_get_next_available_child
|
||||
of_get_next_child
|
||||
of_iomap
|
||||
of_machine_is_compatible
|
||||
of_match_device
|
||||
of_match_node
|
||||
of_nvmem_cell_get
|
||||
of_parse_phandle
|
||||
of_property_count_elems_of_size
|
||||
of_property_read_string
|
||||
of_property_read_string_helper
|
||||
of_property_read_u32_index
|
||||
of_property_read_variable_u32_array
|
||||
panic_notifier_list
|
||||
param_ops_int
|
||||
__per_cpu_offset
|
||||
__platform_driver_probe
|
||||
__platform_driver_register
|
||||
platform_driver_unregister
|
||||
platform_get_irq
|
||||
platform_get_resource
|
||||
pm_clk_create
|
||||
pm_clk_destroy
|
||||
power_supply_am_i_supplied
|
||||
power_supply_changed
|
||||
power_supply_get_battery_info
|
||||
power_supply_get_by_phandle
|
||||
power_supply_get_drvdata
|
||||
power_supply_get_property
|
||||
power_supply_put_battery_info
|
||||
power_supply_register
|
||||
power_supply_reg_notifier
|
||||
power_supply_unregister
|
||||
print_hex_dump
|
||||
printk
|
||||
__put_task_struct
|
||||
queue_delayed_work_on
|
||||
queue_work_on
|
||||
rdev_get_drvdata
|
||||
register_pm_notifier
|
||||
regmap_bulk_read
|
||||
regmap_field_read
|
||||
regmap_field_update_bits_base
|
||||
regmap_raw_read
|
||||
regmap_raw_write
|
||||
regmap_read
|
||||
regmap_update_bits_base
|
||||
regmap_write
|
||||
regulator_disable
|
||||
regulator_enable
|
||||
regulator_get_voltage
|
||||
regulator_put
|
||||
regulator_set_voltage
|
||||
reset_control_assert
|
||||
reset_control_deassert
|
||||
snprintf
|
||||
sprintf
|
||||
sscanf
|
||||
__stack_chk_fail
|
||||
strcmp
|
||||
syscon_node_to_regmap
|
||||
syscon_regmap_lookup_by_phandle
|
||||
sysfs_create_file_ns
|
||||
system_freezable_wq
|
||||
system_wq
|
||||
thermal_zone_get_zone_by_name
|
||||
__traceiter_rwmmio_post_read
|
||||
__traceiter_rwmmio_read
|
||||
__traceiter_rwmmio_write
|
||||
__tracepoint_rwmmio_post_read
|
||||
__tracepoint_rwmmio_read
|
||||
__tracepoint_rwmmio_write
|
||||
__udelay
|
||||
update_devfreq
|
||||
up_read
|
||||
up_write
|
||||
usleep_range
|
||||
|
||||
# required by bq25700_charger.ko
|
||||
extcon_get_edev_by_phandle
|
||||
extcon_get_state
|
||||
extcon_register_notifier
|
||||
irq_set_irq_type
|
||||
of_find_compatible_node
|
||||
power_supply_get_by_name
|
||||
|
||||
# required by bq25890_charger.ko
|
||||
devm_gpiod_get
|
||||
devm_usb_get_phy
|
||||
gpiod_to_irq
|
||||
system_power_efficient_wq
|
||||
|
||||
# required by clk-link.ko
|
||||
pm_clk_add
|
||||
pm_clk_resume
|
||||
pm_clk_suspend
|
||||
__pm_runtime_disable
|
||||
pm_runtime_enable
|
||||
|
||||
# required by clk-pwm.ko
|
||||
devm_pwm_get
|
||||
of_clk_add_hw_provider
|
||||
of_clk_hw_simple_get
|
||||
pwm_apply_state
|
||||
|
||||
# required by clk-rockchip.ko
|
||||
clk_divider_ops
|
||||
clk_divider_ro_ops
|
||||
clk_fixed_factor_ops
|
||||
clk_fractional_divider_ops
|
||||
__clk_get_hw
|
||||
clk_get_parent
|
||||
clk_hw_get_flags
|
||||
clk_hw_get_name
|
||||
clk_hw_get_parent
|
||||
clk_hw_get_rate
|
||||
clk_hw_register_composite
|
||||
clk_hw_round_rate
|
||||
__clk_mux_determine_rate
|
||||
clk_mux_ops
|
||||
clk_mux_ro_ops
|
||||
clk_notifier_unregister
|
||||
clk_register_divider_table
|
||||
clk_register_fixed_factor
|
||||
clk_register_gate
|
||||
clk_register_mux_table
|
||||
clk_unregister
|
||||
gcd
|
||||
kmemdup
|
||||
match_string
|
||||
of_clk_src_onecell_get
|
||||
rational_best_approximation
|
||||
_raw_spin_lock_irqsave
|
||||
_raw_spin_unlock_irqrestore
|
||||
register_restart_handler
|
||||
reset_controller_register
|
||||
__warn_printk
|
||||
|
||||
# required by clk-scmi.ko
|
||||
clk_hw_set_rate_range
|
||||
devm_of_clk_add_hw_provider
|
||||
of_clk_hw_onecell_get
|
||||
scmi_driver_register
|
||||
scmi_driver_unregister
|
||||
|
||||
# required by cpufreq-dt.ko
|
||||
cpufreq_enable_boost_support
|
||||
cpufreq_freq_attr_scaling_available_freqs
|
||||
cpufreq_freq_attr_scaling_boost_freqs
|
||||
cpufreq_generic_frequency_table_verify
|
||||
cpufreq_generic_get
|
||||
cpufreq_register_driver
|
||||
cpufreq_unregister_driver
|
||||
dev_pm_opp_free_cpufreq_table
|
||||
dev_pm_opp_get_max_transition_latency
|
||||
dev_pm_opp_get_sharing_cpus
|
||||
dev_pm_opp_get_suspend_opp_freq
|
||||
dev_pm_opp_init_cpufreq_table
|
||||
dev_pm_opp_of_cpumask_add_table
|
||||
dev_pm_opp_of_cpumask_remove_table
|
||||
dev_pm_opp_of_register_em
|
||||
dev_pm_opp_set_sharing_cpus
|
||||
policy_has_boost_freq
|
||||
|
||||
# required by cpufreq_ondemand.ko
|
||||
cpufreq_cpu_get_raw
|
||||
cpufreq_dbs_governor_exit
|
||||
cpufreq_dbs_governor_init
|
||||
cpufreq_dbs_governor_limits
|
||||
cpufreq_dbs_governor_start
|
||||
cpufreq_dbs_governor_stop
|
||||
cpufreq_table_index_unsorted
|
||||
dbs_update
|
||||
get_cpu_idle_time_us
|
||||
gov_update_cpu_data
|
||||
preempt_schedule
|
||||
store_sampling_rate
|
||||
|
||||
# required by cw2015_battery.ko
|
||||
dev_err_probe
|
||||
|
||||
# required by cw2017_battery.ko
|
||||
bcmp
|
||||
|
||||
# required by cw221x_battery.ko
|
||||
cancel_delayed_work
|
||||
destroy_workqueue
|
||||
|
||||
# required by industrialio-triggered-buffer.ko
|
||||
iio_alloc_pollfunc
|
||||
iio_dealloc_pollfunc
|
||||
iio_device_attach_buffer
|
||||
|
||||
# required by io-domain.ko
|
||||
_dev_crit
|
||||
regulator_register_notifier
|
||||
regulator_unregister_notifier
|
||||
|
||||
# required by kfifo_buf.ko
|
||||
iio_buffer_init
|
||||
iio_buffer_put
|
||||
__kfifo_alloc
|
||||
__kfifo_free
|
||||
__kfifo_in
|
||||
__kfifo_to_user
|
||||
mutex_lock_interruptible
|
||||
|
||||
# required by nvmem-rockchip-otp.ko
|
||||
devm_clk_bulk_get
|
||||
param_ops_uint
|
||||
|
||||
# required by pm_domains.ko
|
||||
clk_bulk_put
|
||||
of_genpd_add_provider_onecell
|
||||
panic
|
||||
param_ops_bool
|
||||
pm_clk_add_clk
|
||||
pm_genpd_add_subdomain
|
||||
pm_genpd_init
|
||||
pm_genpd_remove
|
||||
strrchr
|
||||
|
||||
# required by rockchip-cpufreq.ko
|
||||
cpufreq_unregister_notifier
|
||||
dev_pm_opp_put_prop_name
|
||||
dev_pm_opp_set_supported_hw
|
||||
of_property_match_string
|
||||
platform_device_register_full
|
||||
|
||||
# required by rockchip-cpuinfo.ko
|
||||
nvmem_cell_get
|
||||
|
||||
# required by rockchip-dfi.ko
|
||||
devm_devfreq_event_add_edev
|
||||
gic_nonsecure_priorities
|
||||
|
||||
# required by rockchip.ko
|
||||
__genphy_config_aneg
|
||||
genphy_resume
|
||||
genphy_soft_reset
|
||||
genphy_suspend
|
||||
mdiobus_read
|
||||
mdiobus_write
|
||||
phy_drivers_register
|
||||
phy_drivers_unregister
|
||||
|
||||
# required by rockchip_bus.ko
|
||||
cpu_topology
|
||||
|
||||
# required by rockchip_debug.ko
|
||||
nr_irqs
|
||||
|
||||
# required by rockchip_dmc.ko
|
||||
cpufreq_cpu_get
|
||||
cpufreq_cpu_put
|
||||
cpufreq_quick_get
|
||||
devfreq_add_governor
|
||||
devfreq_event_disable_edev
|
||||
devfreq_event_enable_edev
|
||||
devfreq_event_get_edev_by_phandle
|
||||
devfreq_event_get_edev_count
|
||||
devfreq_event_get_event
|
||||
devfreq_monitor_resume
|
||||
devfreq_monitor_start
|
||||
devfreq_monitor_stop
|
||||
devfreq_monitor_suspend
|
||||
devfreq_resume_device
|
||||
devfreq_suspend_device
|
||||
devfreq_update_interval
|
||||
devm_devfreq_add_device
|
||||
devm_devfreq_register_opp_notifier
|
||||
_dev_notice
|
||||
dev_pm_opp_unregister_set_opp_helper
|
||||
disable_irq
|
||||
enable_irq
|
||||
finish_wait
|
||||
init_wait_entry
|
||||
__init_waitqueue_head
|
||||
input_close_device
|
||||
input_open_device
|
||||
input_register_handle
|
||||
input_register_handler
|
||||
input_unregister_handle
|
||||
kstrtouint
|
||||
__memset_io
|
||||
of_devfreq_cooling_register_power
|
||||
platform_get_irq_byname
|
||||
prepare_to_wait_event
|
||||
___ratelimit
|
||||
schedule_timeout
|
||||
__wake_up
|
||||
|
||||
# required by rockchip_dmc_common.ko
|
||||
down_write_trylock
|
||||
|
||||
# required by rockchip_opp_select.ko
|
||||
dev_pm_opp_disable
|
||||
dev_pm_opp_of_add_table
|
||||
dev_pm_opp_set_prop_name
|
||||
of_find_node_opts_by_path
|
||||
regulator_get_linear_step
|
||||
regulator_get_optional
|
||||
|
||||
# required by rockchip_pm_config.ko
|
||||
of_get_named_gpio_flags
|
||||
|
||||
# required by rockchip_pvtm.ko
|
||||
debugfs_create_dir
|
||||
debugfs_create_file
|
||||
debugfs_remove
|
||||
seq_lseek
|
||||
seq_printf
|
||||
seq_puts
|
||||
seq_read
|
||||
single_open
|
||||
single_release
|
||||
|
||||
# required by rockchip_pwm_remotectl.ko
|
||||
devm_input_allocate_device
|
||||
input_event
|
||||
input_register_device
|
||||
input_set_capability
|
||||
irq_set_affinity_hint
|
||||
jiffies
|
||||
jiffies_to_msecs
|
||||
mod_timer
|
||||
of_get_property
|
||||
__pm_relax
|
||||
pm_wakeup_ws_event
|
||||
__tasklet_hi_schedule
|
||||
tasklet_init
|
||||
wakeup_source_add
|
||||
wakeup_source_remove
|
||||
|
||||
# required by rockchip_saradc.ko
|
||||
complete
|
||||
devm_add_action
|
||||
devm_iio_device_alloc
|
||||
__devm_iio_device_register
|
||||
__devm_reset_control_get
|
||||
find_next_bit
|
||||
iio_get_time_ns
|
||||
iio_push_to_buffers
|
||||
iio_trigger_notify_done
|
||||
__init_swait_queue_head
|
||||
wait_for_completion_timeout
|
||||
|
||||
# required by rockchip_sip.ko
|
||||
arm64_use_ng_mappings
|
||||
__arm_smccc_smc
|
||||
__ioremap
|
||||
memstart_addr
|
||||
pfn_valid
|
||||
sched_clock
|
||||
vmap
|
||||
|
||||
# required by rockchip_system_monitor.ko
|
||||
add_cpu
|
||||
bitmap_parselist
|
||||
blocking_notifier_call_chain
|
||||
blocking_notifier_chain_register
|
||||
blocking_notifier_chain_unregister
|
||||
dev_pm_opp_find_freq_floor
|
||||
dev_pm_qos_add_request
|
||||
dev_pm_qos_remove_request
|
||||
dev_pm_qos_update_request
|
||||
kobject_create_and_add
|
||||
kstrdup
|
||||
kstrtoull
|
||||
mod_delayed_work_on
|
||||
register_reboot_notifier
|
||||
regulator_get
|
||||
remove_cpu
|
||||
strchr
|
||||
strsep
|
||||
strstr
|
||||
thermal_zone_get_temp
|
||||
|
||||
# required by rockchip_thermal.ko
|
||||
devm_pinctrl_get
|
||||
devm_thermal_zone_of_sensor_register
|
||||
pinctrl_lookup_state
|
||||
pinctrl_select_state
|
||||
thermal_zone_device_disable
|
||||
thermal_zone_device_enable
|
||||
thermal_zone_device_update
|
||||
|
||||
# required by rtc-hym8563.ko
|
||||
_bcd2bin
|
||||
_bin2bcd
|
||||
devm_rtc_device_register
|
||||
i2c_smbus_read_byte_data
|
||||
i2c_smbus_write_byte_data
|
||||
rtc_valid_tm
|
||||
|
||||
# required by sgm41542_charger.ko
|
||||
regulator_unregister
|
||||
strncpy
|
||||
|
||||
# required by timer-rockchip.ko
|
||||
clockevents_config_and_register
|
||||
irq_of_parse_and_map
|
||||
request_threaded_irq
|
||||
@@ -1182,7 +1182,6 @@ config ARCH_SPLIT_ARG64
|
||||
|
||||
config ARCH_HAS_NONLEAF_PMD_YOUNG
|
||||
bool
|
||||
depends on PGTABLE_LEVELS > 2
|
||||
help
|
||||
Architectures that select this option are capable of setting the
|
||||
accessed bit in non-leaf PMD entries when using them as part of linear
|
||||
|
||||
@@ -152,6 +152,7 @@ config ARCH_MEDIATEK
|
||||
|
||||
config ARCH_MESON
|
||||
bool "Amlogic Platforms"
|
||||
select COMMON_CLK
|
||||
help
|
||||
This enables support for the arm64 based Amlogic SoCs
|
||||
such as the s905, S905X/D, S912, A113X/D or S905X/D2
|
||||
|
||||
@@ -513,6 +513,7 @@ CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
|
||||
CONFIG_USB_CONFIGFS_F_UAC2=y
|
||||
CONFIG_USB_CONFIGFS_F_MIDI=y
|
||||
CONFIG_USB_CONFIGFS_F_HID=y
|
||||
CONFIG_USB_CONFIGFS_F_UVC=y
|
||||
CONFIG_TYPEC=y
|
||||
CONFIG_TYPEC_TCPM=y
|
||||
CONFIG_TYPEC_TCPCI=y
|
||||
|
||||
342
arch/arm64/configs/rockchip_gki.fragment
Normal file
342
arch/arm64/configs/rockchip_gki.fragment
Normal file
@@ -0,0 +1,342 @@
|
||||
CONFIG_AP6XXX=m
|
||||
CONFIG_ARCH_ROCKCHIP=y
|
||||
CONFIG_ARM_ROCKCHIP_BUS_DEVFREQ=m
|
||||
CONFIG_ARM_ROCKCHIP_CPUFREQ=m
|
||||
CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ=m
|
||||
CONFIG_BACKLIGHT_PWM=m
|
||||
CONFIG_BATTERY_CW2015=m
|
||||
CONFIG_BATTERY_CW2017=m
|
||||
CONFIG_BATTERY_CW221X=m
|
||||
CONFIG_BATTERY_RK817=m
|
||||
CONFIG_BATTERY_RK818=m
|
||||
CONFIG_BLK_DEV_NVME=m
|
||||
CONFIG_BMA2XX_ACC=m
|
||||
CONFIG_CHARGER_BQ25700=m
|
||||
CONFIG_CHARGER_BQ25890=m
|
||||
CONFIG_CHARGER_RK817=m
|
||||
CONFIG_CHARGER_RK818=m
|
||||
CONFIG_CHARGER_SC89890=m
|
||||
CONFIG_CHARGER_SGM41542=m
|
||||
CONFIG_CHR_DEV_SCH=m
|
||||
CONFIG_CHR_DEV_SG=m
|
||||
CONFIG_COMMON_CLK_PWM=m
|
||||
CONFIG_COMMON_CLK_RK808=m
|
||||
CONFIG_COMMON_CLK_ROCKCHIP=m
|
||||
CONFIG_COMMON_CLK_SCMI=m
|
||||
CONFIG_COMPASS_AK8963=m
|
||||
CONFIG_COMPASS_AK8975=m
|
||||
CONFIG_COMPASS_DEVICE=m
|
||||
CONFIG_CPUFREQ_DT=m
|
||||
CONFIG_CPU_FREQ_GOV_ONDEMAND=m
|
||||
CONFIG_CPU_FREQ_GOV_USERSPACE=m
|
||||
CONFIG_CPU_RK3588=y
|
||||
CONFIG_CRYPTO_AES_ARM64_CE_CCM=m
|
||||
CONFIG_CRYPTO_DEV_ROCKCHIP=m
|
||||
CONFIG_CRYPTO_DEV_ROCKCHIP_DEV=m
|
||||
CONFIG_CRYPTO_GHASH_ARM64_CE=m
|
||||
CONFIG_CRYPTO_SHA1_ARM64_CE=m
|
||||
CONFIG_CRYPTO_TWOFISH=m
|
||||
CONFIG_DEVFREQ_EVENT_ROCKCHIP_NOCP=m
|
||||
CONFIG_DMABUF_HEAPS_CMA=m
|
||||
CONFIG_DMABUF_HEAPS_SYSTEM=m
|
||||
CONFIG_DRAGONRISE_FF=y
|
||||
CONFIG_DRM_DISPLAY_CONNECTOR=m
|
||||
CONFIG_DRM_DW_HDMI_CEC=m
|
||||
CONFIG_DRM_DW_HDMI_I2S_AUDIO=m
|
||||
CONFIG_DRM_MAXIM_MAX96745=m
|
||||
CONFIG_DRM_MAXIM_MAX96752F=m
|
||||
CONFIG_DRM_MAXIM_MAX96755F=m
|
||||
CONFIG_DRM_PANEL_SIMPLE=m
|
||||
CONFIG_DRM_RK1000_TVE=m
|
||||
CONFIG_DRM_RK630_TVE=m
|
||||
CONFIG_DRM_ROCKCHIP=m
|
||||
CONFIG_DRM_ROCKCHIP_RK628=m
|
||||
CONFIG_DRM_ROHM_BU18XL82=m
|
||||
CONFIG_DRM_SII902X=m
|
||||
CONFIG_DTC_SYMBOLS=y
|
||||
CONFIG_DW_WATCHDOG=m
|
||||
CONFIG_GPIO_ROCKCHIP=m
|
||||
CONFIG_GREENASIA_FF=y
|
||||
CONFIG_GSENSOR_DEVICE=m
|
||||
CONFIG_GS_DA223=m
|
||||
CONFIG_GS_KXTJ9=m
|
||||
CONFIG_GS_LIS3DH=m
|
||||
CONFIG_GS_LSM303D=m
|
||||
CONFIG_GS_MC3230=m
|
||||
CONFIG_GS_MMA7660=m
|
||||
CONFIG_GS_MMA8452=m
|
||||
CONFIG_GS_MXC6655XA=m
|
||||
CONFIG_GS_SC7660=m
|
||||
CONFIG_GS_SC7A20=m
|
||||
CONFIG_GS_SC7A30=m
|
||||
CONFIG_GYROSCOPE_DEVICE=m
|
||||
CONFIG_GYRO_EWTSA=m
|
||||
CONFIG_GYRO_L3G20D=m
|
||||
CONFIG_GYRO_L3G4200D=m
|
||||
CONFIG_GYRO_LSM330=m
|
||||
CONFIG_GYRO_MPU6500=m
|
||||
CONFIG_GYRO_MPU6880=m
|
||||
CONFIG_HALL_DEVICE=m
|
||||
CONFIG_HID_A4TECH=m
|
||||
CONFIG_HID_ACRUX=m
|
||||
CONFIG_HID_ACRUX_FF=y
|
||||
CONFIG_HID_ALPS=m
|
||||
CONFIG_HID_APPLEIR=m
|
||||
CONFIG_HID_AUREAL=m
|
||||
CONFIG_HID_BELKIN=m
|
||||
CONFIG_HID_CHERRY=m
|
||||
CONFIG_HID_CHICONY=m
|
||||
CONFIG_HID_CYPRESS=m
|
||||
CONFIG_HID_DRAGONRISE=m
|
||||
CONFIG_HID_EMS_FF=m
|
||||
CONFIG_HID_EZKEY=m
|
||||
CONFIG_HID_GREENASIA=m
|
||||
CONFIG_HID_GYRATION=m
|
||||
CONFIG_HID_HOLTEK=m
|
||||
CONFIG_HID_ICADE=m
|
||||
CONFIG_HID_KENSINGTON=m
|
||||
CONFIG_HID_KEYTOUCH=m
|
||||
CONFIG_HID_KYE=m
|
||||
CONFIG_HID_LCPOWER=m
|
||||
CONFIG_HID_LENOVO=m
|
||||
CONFIG_HID_MONTEREY=m
|
||||
CONFIG_HID_NTRIG=m
|
||||
CONFIG_HID_ORTEK=m
|
||||
CONFIG_HID_PANTHERLORD=m
|
||||
CONFIG_HID_PETALYNX=m
|
||||
CONFIG_HID_PRIMAX=m
|
||||
CONFIG_HID_SAITEK=m
|
||||
CONFIG_HID_SAMSUNG=m
|
||||
CONFIG_HID_SMARTJOYPLUS=m
|
||||
CONFIG_HID_SPEEDLINK=m
|
||||
CONFIG_HID_STEELSERIES=m
|
||||
CONFIG_HID_SUNPLUS=m
|
||||
CONFIG_HID_THINGM=m
|
||||
CONFIG_HID_THRUSTMASTER=m
|
||||
CONFIG_HID_TIVO=m
|
||||
CONFIG_HID_TOPSEED=m
|
||||
CONFIG_HID_TWINHAN=m
|
||||
CONFIG_HID_WALTOP=m
|
||||
CONFIG_HID_ZEROPLUS=m
|
||||
CONFIG_HID_ZYDACRON=m
|
||||
CONFIG_HS_MH248=m
|
||||
CONFIG_HW_RANDOM_ROCKCHIP=m
|
||||
CONFIG_I2C_CHARDEV=m
|
||||
CONFIG_I2C_GPIO=m
|
||||
CONFIG_I2C_HID=m
|
||||
CONFIG_I2C_RK3X=m
|
||||
CONFIG_IEP=m
|
||||
CONFIG_IIO_BUFFER_CB=m
|
||||
CONFIG_INPUT_RK805_PWRKEY=m
|
||||
CONFIG_KEYBOARD_ADC=m
|
||||
CONFIG_LEDS_GPIO=m
|
||||
CONFIG_LEDS_RGB13H=m
|
||||
CONFIG_LEDS_TRIGGER_BACKLIGHT=m
|
||||
CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
|
||||
CONFIG_LEDS_TRIGGER_HEARTBEAT=m
|
||||
CONFIG_LIGHT_DEVICE=m
|
||||
CONFIG_LSM330_ACC=m
|
||||
CONFIG_LS_CM3217=m
|
||||
CONFIG_LS_CM3218=m
|
||||
CONFIG_LS_STK3410=m
|
||||
CONFIG_LS_UCS14620=m
|
||||
CONFIG_MALI_BIFROST=m
|
||||
CONFIG_MALI_BIFROST_DEBUG=y
|
||||
CONFIG_MALI_BIFROST_EXPERT=y
|
||||
CONFIG_MALI_CSF_SUPPORT=y
|
||||
CONFIG_MALI_PLATFORM_NAME="rk"
|
||||
CONFIG_MALI_PWRSOFT_765=y
|
||||
CONFIG_MFD_RK628=m
|
||||
CONFIG_MFD_RK630_I2C=m
|
||||
CONFIG_MFD_RK806_SPI=m
|
||||
CONFIG_MFD_RK808=m
|
||||
CONFIG_MMC_DW=m
|
||||
CONFIG_MMC_DW_ROCKCHIP=m
|
||||
CONFIG_MMC_SDHCI_OF_ARASAN=m
|
||||
CONFIG_MMC_SDHCI_OF_DWCMSHC=m
|
||||
CONFIG_MPU6500_ACC=m
|
||||
CONFIG_MPU6880_ACC=m
|
||||
CONFIG_OPTEE=m
|
||||
CONFIG_PANTHERLORD_FF=y
|
||||
CONFIG_PCIEASPM_EXT=m
|
||||
CONFIG_PCIE_DW_ROCKCHIP=m
|
||||
CONFIG_PCIE_ROCKCHIP_HOST=m
|
||||
CONFIG_PHY_ROCKCHIP_CSI2_DPHY=m
|
||||
CONFIG_PHY_ROCKCHIP_DP=m
|
||||
CONFIG_PHY_ROCKCHIP_EMMC=m
|
||||
CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=m
|
||||
CONFIG_PHY_ROCKCHIP_INNO_HDMI=m
|
||||
CONFIG_PHY_ROCKCHIP_INNO_USB2=m
|
||||
CONFIG_PHY_ROCKCHIP_INNO_USB3=m
|
||||
CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY=m
|
||||
CONFIG_PHY_ROCKCHIP_NANENG_EDP=m
|
||||
CONFIG_PHY_ROCKCHIP_PCIE=m
|
||||
CONFIG_PHY_ROCKCHIP_SAMSUNG_DCPHY=m
|
||||
CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX=m
|
||||
CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX_HDMI=m
|
||||
CONFIG_PHY_ROCKCHIP_SNPS_PCIE3=m
|
||||
CONFIG_PHY_ROCKCHIP_TYPEC=m
|
||||
CONFIG_PHY_ROCKCHIP_USB=m
|
||||
CONFIG_PHY_ROCKCHIP_USBDP=m
|
||||
CONFIG_PINCTRL_RK805=m
|
||||
CONFIG_PINCTRL_RK806=m
|
||||
CONFIG_PINCTRL_ROCKCHIP=m
|
||||
CONFIG_PL330_DMA=m
|
||||
CONFIG_PROXIMITY_DEVICE=m
|
||||
CONFIG_PS_STK3410=m
|
||||
CONFIG_PS_UCS14620=m
|
||||
CONFIG_PWM_ROCKCHIP=m
|
||||
CONFIG_REGULATOR_ACT8865=m
|
||||
CONFIG_REGULATOR_FAN53555=m
|
||||
CONFIG_REGULATOR_GPIO=m
|
||||
CONFIG_REGULATOR_LP8752=m
|
||||
CONFIG_REGULATOR_MP8865=m
|
||||
CONFIG_REGULATOR_PWM=m
|
||||
CONFIG_REGULATOR_RK806=m
|
||||
CONFIG_REGULATOR_RK808=m
|
||||
CONFIG_REGULATOR_RK860X=m
|
||||
CONFIG_REGULATOR_TPS65132=m
|
||||
CONFIG_REGULATOR_WL2868C=m
|
||||
CONFIG_REGULATOR_XZ3216=m
|
||||
CONFIG_RFKILL_RK=m
|
||||
CONFIG_RK_CONSOLE_THREAD=y
|
||||
CONFIG_RK_HEADSET=m
|
||||
CONFIG_ROCKCHIP_ANALOGIX_DP=y
|
||||
CONFIG_ROCKCHIP_CDN_DP=y
|
||||
CONFIG_ROCKCHIP_CPUINFO=m
|
||||
CONFIG_ROCKCHIP_DEBUG=m
|
||||
CONFIG_ROCKCHIP_DW_DP=y
|
||||
CONFIG_ROCKCHIP_DW_HDCP2=m
|
||||
CONFIG_ROCKCHIP_DW_HDMI=y
|
||||
CONFIG_ROCKCHIP_DW_MIPI_DSI=y
|
||||
CONFIG_ROCKCHIP_EFUSE=m
|
||||
CONFIG_ROCKCHIP_GRF=m
|
||||
CONFIG_ROCKCHIP_INNO_HDMI=y
|
||||
CONFIG_ROCKCHIP_IODOMAIN=m
|
||||
CONFIG_ROCKCHIP_IOMMU=m
|
||||
CONFIG_ROCKCHIP_IPA=m
|
||||
CONFIG_ROCKCHIP_LVDS=y
|
||||
CONFIG_ROCKCHIP_MPP_AV1DEC=y
|
||||
CONFIG_ROCKCHIP_MPP_IEP2=y
|
||||
CONFIG_ROCKCHIP_MPP_JPGDEC=y
|
||||
CONFIG_ROCKCHIP_MPP_RKVDEC=y
|
||||
CONFIG_ROCKCHIP_MPP_RKVDEC2=y
|
||||
CONFIG_ROCKCHIP_MPP_RKVENC=y
|
||||
CONFIG_ROCKCHIP_MPP_RKVENC2=y
|
||||
CONFIG_ROCKCHIP_MPP_SERVICE=m
|
||||
CONFIG_ROCKCHIP_MPP_VDPU1=y
|
||||
CONFIG_ROCKCHIP_MPP_VDPU2=y
|
||||
CONFIG_ROCKCHIP_MPP_VEPU1=y
|
||||
CONFIG_ROCKCHIP_MPP_VEPU2=y
|
||||
CONFIG_ROCKCHIP_MULTI_RGA=m
|
||||
CONFIG_ROCKCHIP_OPP=m
|
||||
CONFIG_ROCKCHIP_OTP=m
|
||||
CONFIG_ROCKCHIP_PHY=m
|
||||
CONFIG_ROCKCHIP_PM_DOMAINS=m
|
||||
CONFIG_ROCKCHIP_PVTM=m
|
||||
CONFIG_ROCKCHIP_REMOTECTL=m
|
||||
CONFIG_ROCKCHIP_REMOTECTL_PWM=m
|
||||
CONFIG_ROCKCHIP_RGB=y
|
||||
CONFIG_ROCKCHIP_RKNPU=m
|
||||
CONFIG_ROCKCHIP_SARADC=m
|
||||
CONFIG_ROCKCHIP_SIP=m
|
||||
CONFIG_ROCKCHIP_SUSPEND_MODE=m
|
||||
CONFIG_ROCKCHIP_SYSTEM_MONITOR=m
|
||||
CONFIG_ROCKCHIP_THERMAL=m
|
||||
CONFIG_ROCKCHIP_TIMER=m
|
||||
CONFIG_ROCKCHIP_VENDOR_STORAGE=m
|
||||
CONFIG_ROCKCHIP_VENDOR_STORAGE_UPDATE_LOADER=y
|
||||
CONFIG_RTC_DRV_HYM8563=m
|
||||
CONFIG_RTC_DRV_RK808=m
|
||||
CONFIG_SENSOR_DEVICE=m
|
||||
CONFIG_SERIAL_8250_DW=m
|
||||
CONFIG_SMARTJOYPLUS_FF=y
|
||||
CONFIG_SND_SIMPLE_CARD=m
|
||||
CONFIG_SND_SOC_BT_SCO=m
|
||||
CONFIG_SND_SOC_CX2072X=m
|
||||
CONFIG_SND_SOC_DUMMY_CODEC=m
|
||||
CONFIG_SND_SOC_ES7202=m
|
||||
CONFIG_SND_SOC_ES7210=m
|
||||
CONFIG_SND_SOC_ES7243E=m
|
||||
CONFIG_SND_SOC_ES8311=m
|
||||
CONFIG_SND_SOC_ES8316=m
|
||||
CONFIG_SND_SOC_ES8323=m
|
||||
CONFIG_SND_SOC_ES8326=m
|
||||
CONFIG_SND_SOC_ES8396=m
|
||||
CONFIG_SND_SOC_RK3328=m
|
||||
CONFIG_SND_SOC_RK817=m
|
||||
CONFIG_SND_SOC_RK_CODEC_DIGITAL=m
|
||||
CONFIG_SND_SOC_ROCKCHIP=m
|
||||
CONFIG_SND_SOC_ROCKCHIP_HDMI=m
|
||||
CONFIG_SND_SOC_ROCKCHIP_I2S=m
|
||||
CONFIG_SND_SOC_ROCKCHIP_I2S_TDM=m
|
||||
CONFIG_SND_SOC_ROCKCHIP_MULTICODECS=m
|
||||
CONFIG_SND_SOC_ROCKCHIP_PDM=m
|
||||
CONFIG_SND_SOC_ROCKCHIP_SPDIF=m
|
||||
CONFIG_SND_SOC_ROCKCHIP_SPDIFRX=m
|
||||
CONFIG_SND_SOC_RT5640=m
|
||||
CONFIG_SND_SOC_SPDIF=m
|
||||
CONFIG_SPI_ROCKCHIP=m
|
||||
CONFIG_SPI_SPIDEV=m
|
||||
CONFIG_SW_SYNC=m
|
||||
CONFIG_SYSCON_REBOOT_MODE=m
|
||||
CONFIG_TEE=m
|
||||
CONFIG_TEST_POWER=m
|
||||
CONFIG_TOUCHSCREEN_ELAN5515=m
|
||||
CONFIG_TOUCHSCREEN_GSL3673=m
|
||||
CONFIG_TOUCHSCREEN_GSLX680_PAD=m
|
||||
CONFIG_TYPEC_DP_ALTMODE=m
|
||||
CONFIG_TYPEC_FUSB302=m
|
||||
CONFIG_TYPEC_HUSB311=m
|
||||
CONFIG_UCS12CM0=m
|
||||
CONFIG_USB_DWC2=m
|
||||
CONFIG_USB_NET_CDC_MBIM=m
|
||||
CONFIG_USB_NET_DM9601=m
|
||||
CONFIG_USB_NET_GL620A=m
|
||||
CONFIG_USB_NET_KALMIA=m
|
||||
CONFIG_USB_NET_MCS7830=m
|
||||
CONFIG_USB_NET_PLUSB=m
|
||||
CONFIG_USB_NET_SMSC75XX=m
|
||||
CONFIG_USB_NET_SMSC95XX=m
|
||||
CONFIG_USB_OHCI_HCD=m
|
||||
# CONFIG_USB_OHCI_HCD_PCI is not set
|
||||
CONFIG_USB_OHCI_HCD_PLATFORM=m
|
||||
CONFIG_USB_PRINTER=m
|
||||
CONFIG_USB_SERIAL=m
|
||||
CONFIG_USB_SERIAL_GENERIC=y
|
||||
CONFIG_USB_TRANCEVIBRATOR=m
|
||||
CONFIG_VIDEO_AW36518=m
|
||||
CONFIG_VIDEO_AW8601=m
|
||||
CONFIG_VIDEO_CN3927V=m
|
||||
CONFIG_VIDEO_DW9714=m
|
||||
CONFIG_VIDEO_FP5510=m
|
||||
CONFIG_VIDEO_GC2145=m
|
||||
CONFIG_VIDEO_GC2385=m
|
||||
CONFIG_VIDEO_GC4C33=m
|
||||
CONFIG_VIDEO_GC8034=m
|
||||
CONFIG_VIDEO_IMX415=m
|
||||
CONFIG_VIDEO_LT6911UXC=m
|
||||
CONFIG_VIDEO_LT7911D=m
|
||||
CONFIG_VIDEO_NVP6188=m
|
||||
CONFIG_VIDEO_OV02B10=m
|
||||
CONFIG_VIDEO_OV13850=m
|
||||
CONFIG_VIDEO_OV13855=m
|
||||
CONFIG_VIDEO_OV50C40=m
|
||||
CONFIG_VIDEO_OV5695=m
|
||||
CONFIG_VIDEO_OV8858=m
|
||||
CONFIG_VIDEO_RK628_BT1120=m
|
||||
CONFIG_VIDEO_RK628_CSI=m
|
||||
CONFIG_VIDEO_RK_IRCUT=m
|
||||
CONFIG_VIDEO_ROCKCHIP_CIF=m
|
||||
CONFIG_VIDEO_ROCKCHIP_ISP=m
|
||||
CONFIG_VIDEO_ROCKCHIP_ISPP=m
|
||||
CONFIG_VIDEO_S5K3L6XX=m
|
||||
CONFIG_VIDEO_S5KJN1=m
|
||||
CONFIG_VIDEO_SGM3784=m
|
||||
CONFIG_VIDEO_THCV244=m
|
||||
CONFIG_VL6180=m
|
||||
CONFIG_WIFI_BUILD_MODULE=y
|
||||
CONFIG_WL_ROCKCHIP=m
|
||||
CONFIG_ZRAM=m
|
||||
CONFIG_ZSMALLOC=m
|
||||
# CONFIG_USB_DUMMY_HCD is not set
|
||||
@@ -107,7 +107,7 @@
|
||||
msr_s SYS_ICC_SRE_EL2, x0
|
||||
isb // Make sure SRE is now set
|
||||
mrs_s x0, SYS_ICC_SRE_EL2 // Read SRE back,
|
||||
tbz x0, #0, 1f // and check that it sticks
|
||||
tbz x0, #0, .Lskip_gicv3_\@ // and check that it sticks
|
||||
msr_s SYS_ICH_HCR_EL2, xzr // Reset ICC_HCR_EL2 to defaults
|
||||
.Lskip_gicv3_\@:
|
||||
.endm
|
||||
|
||||
@@ -75,6 +75,7 @@ enum __kvm_host_smccc_func {
|
||||
__KVM_HOST_SMCCC_FUNC___vgic_v3_save_vmcr_aprs,
|
||||
__KVM_HOST_SMCCC_FUNC___vgic_v3_restore_vmcr_aprs,
|
||||
__KVM_HOST_SMCCC_FUNC___pkvm_init_shadow,
|
||||
__KVM_HOST_SMCCC_FUNC___pkvm_init_shadow_vcpu,
|
||||
__KVM_HOST_SMCCC_FUNC___pkvm_teardown_shadow,
|
||||
__KVM_HOST_SMCCC_FUNC___pkvm_vcpu_load,
|
||||
__KVM_HOST_SMCCC_FUNC___pkvm_vcpu_put,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#ifndef __ASM_MTE_KASAN_H
|
||||
#define __ASM_MTE_KASAN_H
|
||||
|
||||
#include <asm/compiler.h>
|
||||
#include <asm/mte-def.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
@@ -67,7 +67,8 @@ struct bp_hardening_data {
|
||||
|
||||
DECLARE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);
|
||||
|
||||
static inline void arm64_apply_bp_hardening(void)
|
||||
/* Called during entry so must be __always_inline */
|
||||
static __always_inline void arm64_apply_bp_hardening(void)
|
||||
{
|
||||
struct bp_hardening_data *d;
|
||||
|
||||
|
||||
@@ -233,17 +233,20 @@ static void install_bp_hardening_cb(bp_hardening_cb_t fn)
|
||||
__this_cpu_write(bp_hardening_data.slot, HYP_VECTOR_SPECTRE_DIRECT);
|
||||
}
|
||||
|
||||
static void call_smc_arch_workaround_1(void)
|
||||
/* Called during entry so must be noinstr */
|
||||
static noinstr void call_smc_arch_workaround_1(void)
|
||||
{
|
||||
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
|
||||
}
|
||||
|
||||
static void call_hvc_arch_workaround_1(void)
|
||||
/* Called during entry so must be noinstr */
|
||||
static noinstr void call_hvc_arch_workaround_1(void)
|
||||
{
|
||||
arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
|
||||
}
|
||||
|
||||
static void qcom_link_stack_sanitisation(void)
|
||||
/* Called during entry so must be noinstr */
|
||||
static noinstr void qcom_link_stack_sanitisation(void)
|
||||
{
|
||||
u64 tmp;
|
||||
|
||||
|
||||
@@ -2129,6 +2129,17 @@ static int pkvm_drop_host_privileges(void)
|
||||
* once the host stage 2 is installed.
|
||||
*/
|
||||
static_branch_enable(&kvm_protected_mode_initialized);
|
||||
|
||||
/*
|
||||
* Fixup the boot mode so that we don't take spurious round
|
||||
* trips via EL2 on cpu_resume. Flush to the PoC for a good
|
||||
* measure, so that it can be observed by a CPU coming out of
|
||||
* suspend with the MMU off.
|
||||
*/
|
||||
__boot_cpu_mode[0] = __boot_cpu_mode[1] = BOOT_CPU_MODE_EL1;
|
||||
dcache_clean_poc((unsigned long)__boot_cpu_mode,
|
||||
(unsigned long)(__boot_cpu_mode + 2));
|
||||
|
||||
on_each_cpu(_kvm_host_prot_finalize, &ret, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -241,6 +241,14 @@ int handle_exit(struct kvm_vcpu *vcpu, int exception_index)
|
||||
{
|
||||
struct kvm_run *run = vcpu->run;
|
||||
|
||||
if (ARM_SERROR_PENDING(exception_index)) {
|
||||
/*
|
||||
* The SError is handled by handle_exit_early(). If the guest
|
||||
* survives it will re-execute the original instruction.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
exception_index = ARM_EXCEPTION_CODE(exception_index);
|
||||
|
||||
switch (exception_index) {
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <hyp/adjust_pc.h>
|
||||
#include <linux/kvm_host.h>
|
||||
#include <asm/kvm_emulate.h>
|
||||
#include <asm/kvm_mmu.h>
|
||||
|
||||
#if !defined (__KVM_NVHE_HYPERVISOR__) && !defined (__KVM_VHE_HYPERVISOR__)
|
||||
#error Hypervisor code only!
|
||||
@@ -165,7 +166,8 @@ static void enter_exception64(struct kvm_vcpu *vcpu, unsigned long target_mode,
|
||||
*vcpu_pc(vcpu) = vbar + offset;
|
||||
|
||||
old = *vcpu_cpsr(vcpu);
|
||||
new = get_except64_cpsr(old, kvm_has_mte(vcpu->kvm), sctlr, target_mode);
|
||||
new = get_except64_cpsr(old, kvm_has_mte(kern_hyp_va(vcpu->kvm)), sctlr,
|
||||
target_mode);
|
||||
*vcpu_cpsr(vcpu) = new;
|
||||
__vcpu_write_spsr(vcpu, old);
|
||||
}
|
||||
|
||||
@@ -420,7 +420,8 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
|
||||
if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ)
|
||||
vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR);
|
||||
|
||||
if (ARM_SERROR_PENDING(*exit_code)) {
|
||||
if (ARM_SERROR_PENDING(*exit_code) &&
|
||||
ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) {
|
||||
u8 esr_ec = kvm_vcpu_trap_get_class(vcpu);
|
||||
|
||||
/*
|
||||
|
||||
@@ -48,6 +48,12 @@ struct pkvm_iommu_ops {
|
||||
void (*host_stage2_idmap_apply)(struct pkvm_iommu *dev,
|
||||
phys_addr_t start, phys_addr_t end);
|
||||
|
||||
/*
|
||||
* Callback to finish a host stage-2 mapping change at device level.
|
||||
* Called after 'host_stage2_idmap_apply' with host lock held.
|
||||
*/
|
||||
void (*host_stage2_idmap_complete)(struct pkvm_iommu *dev);
|
||||
|
||||
/* Power management callbacks. Called with host lock held. */
|
||||
int (*suspend)(struct pkvm_iommu *dev);
|
||||
int (*resume)(struct pkvm_iommu *dev);
|
||||
|
||||
@@ -42,14 +42,20 @@ struct kvm_shadow_vm {
|
||||
/* The total size of the donated shadow area. */
|
||||
size_t shadow_area_size;
|
||||
|
||||
/*
|
||||
* The number of vcpus initialized and ready to run in the shadow vm.
|
||||
* Modifying this is protected by shadow_lock.
|
||||
*/
|
||||
unsigned int nr_vcpus;
|
||||
|
||||
struct kvm_arch arch;
|
||||
struct kvm_pgtable pgt;
|
||||
struct kvm_pgtable_mm_ops mm_ops;
|
||||
struct hyp_pool pool;
|
||||
hyp_spinlock_t lock;
|
||||
|
||||
/* Array of the shadow state per vcpu. */
|
||||
struct shadow_vcpu_state shadow_vcpus[0];
|
||||
/* Array of the shadow state pointers per vcpu. */
|
||||
struct shadow_vcpu_state *shadow_vcpus[0];
|
||||
};
|
||||
|
||||
static inline bool vcpu_is_protected(struct kvm_vcpu *vcpu)
|
||||
@@ -65,6 +71,9 @@ extern phys_addr_t pvmfw_size;
|
||||
|
||||
void hyp_shadow_table_init(void *tbl);
|
||||
int __pkvm_init_shadow(struct kvm *kvm, void *shadow_va, size_t size, void *pgd);
|
||||
int __pkvm_init_shadow_vcpu(unsigned int shadow_handle,
|
||||
struct kvm_vcpu *host_vcpu,
|
||||
void *shadow_vcpu_hva);
|
||||
int __pkvm_teardown_shadow(int shadow_handle);
|
||||
struct kvm_vcpu *get_shadow_vcpu(int shadow_handle, unsigned int vcpu_idx);
|
||||
void put_shadow_vcpu(struct kvm_vcpu *vcpu);
|
||||
|
||||
@@ -1006,6 +1006,17 @@ static void handle___pkvm_init_shadow(struct kvm_cpu_context *host_ctxt)
|
||||
shadow_size, pgd);
|
||||
}
|
||||
|
||||
static void handle___pkvm_init_shadow_vcpu(struct kvm_cpu_context *host_ctxt)
|
||||
{
|
||||
DECLARE_REG(unsigned int, shadow_handle, host_ctxt, 1);
|
||||
DECLARE_REG(struct kvm_vcpu *, host_vcpu, host_ctxt, 2);
|
||||
DECLARE_REG(void *, shadow_vcpu_hva, host_ctxt, 3);
|
||||
|
||||
cpu_reg(host_ctxt, 1) = __pkvm_init_shadow_vcpu(shadow_handle,
|
||||
host_vcpu,
|
||||
shadow_vcpu_hva);
|
||||
}
|
||||
|
||||
static void handle___pkvm_teardown_shadow(struct kvm_cpu_context *host_ctxt)
|
||||
{
|
||||
DECLARE_REG(int, shadow_handle, host_ctxt, 1);
|
||||
@@ -1079,6 +1090,7 @@ static const hcall_t host_hcall[] = {
|
||||
HANDLE_FUNC(__vgic_v3_save_vmcr_aprs),
|
||||
HANDLE_FUNC(__vgic_v3_restore_vmcr_aprs),
|
||||
HANDLE_FUNC(__pkvm_init_shadow),
|
||||
HANDLE_FUNC(__pkvm_init_shadow_vcpu),
|
||||
HANDLE_FUNC(__pkvm_teardown_shadow),
|
||||
HANDLE_FUNC(__pkvm_vcpu_load),
|
||||
HANDLE_FUNC(__pkvm_vcpu_put),
|
||||
|
||||
@@ -546,4 +546,9 @@ void pkvm_iommu_host_stage2_idmap(phys_addr_t start, phys_addr_t end,
|
||||
if (dev->powered && dev->ops->host_stage2_idmap_apply)
|
||||
dev->ops->host_stage2_idmap_apply(dev, start, end);
|
||||
}
|
||||
|
||||
list_for_each_entry(dev, &iommu_list, list) {
|
||||
if (dev->powered && dev->ops->host_stage2_idmap_complete)
|
||||
dev->ops->host_stage2_idmap_complete(dev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
|
||||
#define PA_MAX ((phys_addr_t)SZ_1G * NR_GIGABYTES)
|
||||
|
||||
#define SYNC_MAX_RETRIES 5
|
||||
#define SYNC_TIMEOUT 5
|
||||
#define SYNC_TIMEOUT_MULTIPLIER 3
|
||||
|
||||
#define CTX_CFG_ENTRY(ctxid, nr_ctx, vid) \
|
||||
(CONTEXT_CFG_VALID_VID_CTX_VID(ctxid, vid) \
|
||||
| (((ctxid) < (nr_ctx)) ? CONTEXT_CFG_VALID_VID_CTX_VALID(ctxid) : 0))
|
||||
@@ -158,11 +162,20 @@ static void __set_control_regs(struct pkvm_iommu *dev)
|
||||
writel_relaxed(ctrl0, dev->va + REG_NS_CTRL0);
|
||||
}
|
||||
|
||||
/* Poll the given SFR until its value has all bits of a given mask set. */
|
||||
static void __wait_until(void __iomem *addr, u32 mask)
|
||||
/*
|
||||
* Poll the given SFR until its value has all bits of a given mask set.
|
||||
* Returns true if successful, false if not successful after a given number of
|
||||
* attempts.
|
||||
*/
|
||||
static bool __wait_until(void __iomem *addr, u32 mask, size_t max_attempts)
|
||||
{
|
||||
while ((readl_relaxed(addr) & mask) != mask)
|
||||
continue;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < max_attempts; i++) {
|
||||
if ((readl_relaxed(addr) & mask) == mask)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Poll the given SFR as long as its value has all bits of a given mask set. */
|
||||
@@ -172,17 +185,54 @@ static void __wait_while(void __iomem *addr, u32 mask)
|
||||
continue;
|
||||
}
|
||||
|
||||
static void __wait_for_invalidation_complete(struct pkvm_iommu *dev)
|
||||
static void __sync_cmd_start(struct pkvm_iommu *sync)
|
||||
{
|
||||
struct pkvm_iommu *sync;
|
||||
writel_relaxed(SYNC_CMD_SYNC, sync->va + REG_NS_SYNC_CMD);
|
||||
}
|
||||
|
||||
static void __invalidation_barrier_slow(struct pkvm_iommu *sync)
|
||||
{
|
||||
size_t i, timeout;
|
||||
|
||||
/*
|
||||
* Wait for transactions to drain if SysMMU_SYNCs were registered.
|
||||
* Assumes that they are in the same power domain as the S2MPU.
|
||||
*
|
||||
* The algorithm will try initiating the SYNC if the SYNC_COMP_COMPLETE
|
||||
* bit has not been set after a given number of attempts, increasing the
|
||||
* timeout exponentially each time. If this cycle fails a given number
|
||||
* of times, the algorithm will give up completely to avoid deadlock.
|
||||
*/
|
||||
timeout = SYNC_TIMEOUT;
|
||||
for (i = 0; i < SYNC_MAX_RETRIES; i++) {
|
||||
__sync_cmd_start(sync);
|
||||
if (__wait_until(sync->va + REG_NS_SYNC_COMP, SYNC_COMP_COMPLETE, timeout))
|
||||
break;
|
||||
timeout *= SYNC_TIMEOUT_MULTIPLIER;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initiate invalidation barrier. */
|
||||
static void __invalidation_barrier_init(struct pkvm_iommu *dev)
|
||||
{
|
||||
struct pkvm_iommu *sync;
|
||||
|
||||
for_each_child(sync, dev)
|
||||
__sync_cmd_start(sync);
|
||||
}
|
||||
|
||||
/* Wait for invalidation to complete. */
|
||||
static void __invalidation_barrier_complete(struct pkvm_iommu *dev)
|
||||
{
|
||||
struct pkvm_iommu *sync;
|
||||
|
||||
/*
|
||||
* Check if the SYNC_COMP_COMPLETE bit has been set for individual
|
||||
* devices. If not, fall back to non-parallel invalidation.
|
||||
*/
|
||||
for_each_child(sync, dev) {
|
||||
writel_relaxed(SYNC_CMD_SYNC, sync->va + REG_NS_SYNC_CMD);
|
||||
__wait_until(sync->va + REG_NS_SYNC_COMP, SYNC_COMP_COMPLETE);
|
||||
if (!(readl_relaxed(sync->va + REG_NS_SYNC_COMP) & SYNC_COMP_COMPLETE))
|
||||
__invalidation_barrier_slow(sync);
|
||||
}
|
||||
|
||||
/* Must not access SFRs while S2MPU is busy invalidating (v9 only). */
|
||||
@@ -195,11 +245,12 @@ static void __wait_for_invalidation_complete(struct pkvm_iommu *dev)
|
||||
static void __all_invalidation(struct pkvm_iommu *dev)
|
||||
{
|
||||
writel_relaxed(INVALIDATION_INVALIDATE, dev->va + REG_NS_ALL_INVALIDATION);
|
||||
__wait_for_invalidation_complete(dev);
|
||||
__invalidation_barrier_init(dev);
|
||||
__invalidation_barrier_complete(dev);
|
||||
}
|
||||
|
||||
static void __range_invalidation(struct pkvm_iommu *dev, phys_addr_t first_byte,
|
||||
phys_addr_t last_byte)
|
||||
static void __range_invalidation_init(struct pkvm_iommu *dev, phys_addr_t first_byte,
|
||||
phys_addr_t last_byte)
|
||||
{
|
||||
u32 start_ppn = first_byte >> RANGE_INVALIDATION_PPN_SHIFT;
|
||||
u32 end_ppn = last_byte >> RANGE_INVALIDATION_PPN_SHIFT;
|
||||
@@ -207,7 +258,7 @@ static void __range_invalidation(struct pkvm_iommu *dev, phys_addr_t first_byte,
|
||||
writel_relaxed(start_ppn, dev->va + REG_NS_RANGE_INVALIDATION_START_PPN);
|
||||
writel_relaxed(end_ppn, dev->va + REG_NS_RANGE_INVALIDATION_END_PPN);
|
||||
writel_relaxed(INVALIDATION_INVALIDATE, dev->va + REG_NS_RANGE_INVALIDATION);
|
||||
__wait_for_invalidation_complete(dev);
|
||||
__invalidation_barrier_init(dev);
|
||||
}
|
||||
|
||||
static void __set_l1entry_attr_with_prot(struct pkvm_iommu *dev, unsigned int gb,
|
||||
@@ -341,7 +392,13 @@ static void __mpt_idmap_apply(struct pkvm_iommu *dev, struct mpt *mpt,
|
||||
__set_l1entry_attr_with_fmpt(dev, gb, vid, fmpt);
|
||||
}
|
||||
}
|
||||
__range_invalidation(dev, first_byte, last_byte);
|
||||
/* Initiate invalidation, completed in __mdt_idmap_complete. */
|
||||
__range_invalidation_init(dev, first_byte, last_byte);
|
||||
}
|
||||
|
||||
static void __mpt_idmap_complete(struct pkvm_iommu *dev, struct mpt *mpt)
|
||||
{
|
||||
__invalidation_barrier_complete(dev);
|
||||
}
|
||||
|
||||
static void s2mpu_host_stage2_idmap_prepare(phys_addr_t start, phys_addr_t end,
|
||||
@@ -362,6 +419,11 @@ static void s2mpu_host_stage2_idmap_apply(struct pkvm_iommu *dev,
|
||||
__mpt_idmap_apply(dev, &host_mpt, start, end - 1);
|
||||
}
|
||||
|
||||
static void s2mpu_host_stage2_idmap_complete(struct pkvm_iommu *dev)
|
||||
{
|
||||
__mpt_idmap_complete(dev, &host_mpt);
|
||||
}
|
||||
|
||||
static int s2mpu_resume(struct pkvm_iommu *dev)
|
||||
{
|
||||
/*
|
||||
@@ -550,6 +612,7 @@ const struct pkvm_iommu_ops pkvm_s2mpu_ops = (struct pkvm_iommu_ops){
|
||||
.suspend = s2mpu_suspend,
|
||||
.host_stage2_idmap_prepare = s2mpu_host_stage2_idmap_prepare,
|
||||
.host_stage2_idmap_apply = s2mpu_host_stage2_idmap_apply,
|
||||
.host_stage2_idmap_complete = s2mpu_host_stage2_idmap_complete,
|
||||
.host_dabt_handler = s2mpu_host_dabt_handler,
|
||||
.data_size = sizeof(struct s2mpu_drv_data),
|
||||
};
|
||||
|
||||
@@ -929,6 +929,9 @@ static int host_complete_share(u64 addr, const struct pkvm_mem_transition *tx,
|
||||
{
|
||||
u64 size = tx->nr_pages * PAGE_SIZE;
|
||||
|
||||
if (tx->initiator.id == PKVM_ID_GUEST)
|
||||
psci_mem_protect_dec();
|
||||
|
||||
return __host_set_page_state_range(addr, size, PKVM_PAGE_SHARED_BORROWED);
|
||||
}
|
||||
|
||||
@@ -937,6 +940,9 @@ static int host_complete_unshare(u64 addr, const struct pkvm_mem_transition *tx)
|
||||
u64 size = tx->nr_pages * PAGE_SIZE;
|
||||
pkvm_id owner_id = initiator_owner_id(tx);
|
||||
|
||||
if (tx->initiator.id == PKVM_ID_GUEST)
|
||||
psci_mem_protect_inc();
|
||||
|
||||
return host_stage2_set_owner_locked(addr, size, owner_id);
|
||||
}
|
||||
|
||||
@@ -1915,7 +1921,14 @@ static int hyp_zero_page(phys_addr_t phys)
|
||||
if (!addr)
|
||||
return -EINVAL;
|
||||
memset(addr, 0, PAGE_SIZE);
|
||||
__clean_dcache_guest_page(addr, PAGE_SIZE);
|
||||
/*
|
||||
* Prefer kvm_flush_dcache_to_poc() over __clean_dcache_guest_page()
|
||||
* here as the latter may elide the CMO under the assumption that FWB
|
||||
* will be enabled on CPUs that support it. This is incorrect for the
|
||||
* host stage-2 and would otherwise lead to a malicious host potentially
|
||||
* being able to read the content of newly reclaimed guest pages.
|
||||
*/
|
||||
kvm_flush_dcache_to_poc(addr, PAGE_SIZE);
|
||||
|
||||
return hyp_fixmap_unmap();
|
||||
}
|
||||
|
||||
@@ -276,9 +276,9 @@ struct kvm_vcpu *get_shadow_vcpu(int shadow_handle, unsigned int vcpu_idx)
|
||||
|
||||
hyp_spin_lock(&shadow_lock);
|
||||
vm = find_shadow_by_handle(shadow_handle);
|
||||
if (!vm || vm->created_vcpus <= vcpu_idx)
|
||||
if (!vm || vm->nr_vcpus <= vcpu_idx)
|
||||
goto unlock;
|
||||
vcpu = &vm->shadow_vcpus[vcpu_idx].vcpu;
|
||||
vcpu = &vm->shadow_vcpus[vcpu_idx]->vcpu;
|
||||
|
||||
/* Ensure vcpu isn't loaded on more than one cpu simultaneously. */
|
||||
if (unlikely(vcpu->arch.pkvm.loaded_on_cpu)) {
|
||||
@@ -370,48 +370,28 @@ static int copy_features(struct kvm_vcpu *shadow_vcpu, struct kvm_vcpu *host_vcp
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void unpin_host_vcpus(struct shadow_vcpu_state *shadow_vcpus, int nr_vcpus)
|
||||
static void unpin_host_vcpu(struct shadow_vcpu_state *shadow_vcpu)
|
||||
{
|
||||
int i;
|
||||
struct kvm_vcpu *host_vcpu = shadow_vcpu->vcpu.arch.pkvm.host_vcpu;
|
||||
size_t sve_state_size;
|
||||
void *sve_state = shadow_vcpu->vcpu.arch.sve_state;
|
||||
|
||||
for (i = 0; i < nr_vcpus; i++) {
|
||||
struct kvm_vcpu *host_vcpu = shadow_vcpus[i].vcpu.arch.pkvm.host_vcpu;
|
||||
struct kvm_vcpu *shadow_vcpu = &shadow_vcpus[i].vcpu;
|
||||
size_t sve_state_size;
|
||||
void *sve_state;
|
||||
hyp_unpin_shared_mem(host_vcpu, host_vcpu + 1);
|
||||
|
||||
hyp_unpin_shared_mem(host_vcpu, host_vcpu + 1);
|
||||
if (!sve_state)
|
||||
return;
|
||||
|
||||
if (!test_bit(KVM_ARM_VCPU_SVE, shadow_vcpu->arch.features))
|
||||
continue;
|
||||
|
||||
sve_state = shadow_vcpu->arch.sve_state;
|
||||
sve_state = kern_hyp_va(sve_state);
|
||||
sve_state_size = vcpu_sve_state_size(shadow_vcpu);
|
||||
hyp_unpin_shared_mem(sve_state, sve_state + sve_state_size);
|
||||
}
|
||||
sve_state = kern_hyp_va(sve_state);
|
||||
sve_state_size = vcpu_sve_state_size(&shadow_vcpu->vcpu);
|
||||
hyp_unpin_shared_mem(sve_state, sve_state + sve_state_size);
|
||||
}
|
||||
|
||||
static int set_host_vcpus(struct shadow_vcpu_state *shadow_vcpus, int nr_vcpus,
|
||||
struct kvm_vcpu **vcpu_array, size_t vcpu_array_size)
|
||||
static void unpin_host_vcpus(struct shadow_vcpu_state *shadow_vcpus[], int nr_vcpus)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (vcpu_array_size < sizeof(*vcpu_array) * nr_vcpus)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < nr_vcpus; i++) {
|
||||
struct kvm_vcpu *host_vcpu = kern_hyp_va(vcpu_array[i]);
|
||||
|
||||
if (hyp_pin_shared_mem(host_vcpu, host_vcpu + 1)) {
|
||||
unpin_host_vcpus(shadow_vcpus, i);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
shadow_vcpus[i].vcpu.arch.pkvm.host_vcpu = host_vcpu;
|
||||
}
|
||||
|
||||
return 0;
|
||||
for (i = 0; i < nr_vcpus; i++)
|
||||
unpin_host_vcpu(shadow_vcpus[i]);
|
||||
}
|
||||
|
||||
static int init_ptrauth(struct kvm_vcpu *shadow_vcpu)
|
||||
@@ -423,86 +403,106 @@ static int init_ptrauth(struct kvm_vcpu *shadow_vcpu)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int init_shadow_structs(struct kvm *kvm, struct kvm_shadow_vm *vm,
|
||||
struct kvm_vcpu **vcpu_array, int nr_vcpus)
|
||||
static void init_shadow_vm(struct kvm *kvm, struct kvm_shadow_vm *vm,
|
||||
int nr_vcpus)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
vm->host_kvm = kvm;
|
||||
vm->created_vcpus = nr_vcpus;
|
||||
vm->arch.pkvm.pvmfw_load_addr = kvm->arch.pkvm.pvmfw_load_addr;
|
||||
vm->arch.pkvm.enabled = READ_ONCE(kvm->arch.pkvm.enabled);
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_vcpus; i++) {
|
||||
struct shadow_vcpu_state *shadow_state = &vm->shadow_vcpus[i];
|
||||
struct kvm_vcpu *shadow_vcpu = &shadow_state->vcpu;
|
||||
struct kvm_vcpu *host_vcpu = shadow_vcpu->arch.pkvm.host_vcpu;
|
||||
static int init_shadow_vcpu(struct shadow_vcpu_state *shadow_state,
|
||||
struct kvm_vcpu *host_vcpu,
|
||||
struct kvm_shadow_vm *vm, int vcpu_idx)
|
||||
{
|
||||
struct kvm_vcpu *shadow_vcpu = &shadow_state->vcpu;
|
||||
int ret;
|
||||
|
||||
shadow_vcpu->kvm = kvm;
|
||||
shadow_vcpu->vcpu_id = host_vcpu->vcpu_id;
|
||||
shadow_vcpu->vcpu_idx = i;
|
||||
host_vcpu = kern_hyp_va(host_vcpu);
|
||||
if (hyp_pin_shared_mem(host_vcpu, host_vcpu + 1))
|
||||
return -EBUSY;
|
||||
|
||||
ret = copy_features(shadow_vcpu, host_vcpu);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (host_vcpu->vcpu_idx != vcpu_idx) {
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = init_ptrauth(shadow_vcpu);
|
||||
if (ret)
|
||||
return ret;
|
||||
shadow_vcpu->arch.pkvm.host_vcpu = host_vcpu;
|
||||
shadow_vcpu->kvm = vm->host_kvm;
|
||||
shadow_vcpu->vcpu_id = host_vcpu->vcpu_id;
|
||||
shadow_vcpu->vcpu_idx = vcpu_idx;
|
||||
|
||||
if (test_bit(KVM_ARM_VCPU_SVE, shadow_vcpu->arch.features)) {
|
||||
size_t sve_state_size;
|
||||
void *sve_state;
|
||||
ret = copy_features(shadow_vcpu, host_vcpu);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
shadow_vcpu->arch.sve_state = READ_ONCE(host_vcpu->arch.sve_state);
|
||||
shadow_vcpu->arch.sve_max_vl = READ_ONCE(host_vcpu->arch.sve_max_vl);
|
||||
ret = init_ptrauth(shadow_vcpu);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
sve_state = kern_hyp_va(shadow_vcpu->arch.sve_state);
|
||||
sve_state_size = vcpu_sve_state_size(shadow_vcpu);
|
||||
if (test_bit(KVM_ARM_VCPU_SVE, shadow_vcpu->arch.features)) {
|
||||
size_t sve_state_size;
|
||||
void *sve_state;
|
||||
|
||||
if (!shadow_vcpu->arch.sve_state || !sve_state_size ||
|
||||
hyp_pin_shared_mem(sve_state,
|
||||
sve_state + sve_state_size)) {
|
||||
clear_bit(KVM_ARM_VCPU_SVE,
|
||||
shadow_vcpu->arch.features);
|
||||
shadow_vcpu->arch.sve_state = NULL;
|
||||
shadow_vcpu->arch.sve_max_vl = 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
shadow_vcpu->arch.sve_state =
|
||||
READ_ONCE(host_vcpu->arch.sve_state);
|
||||
shadow_vcpu->arch.sve_max_vl =
|
||||
READ_ONCE(host_vcpu->arch.sve_max_vl);
|
||||
|
||||
if (vm->arch.pkvm.enabled)
|
||||
pkvm_vcpu_init_traps(shadow_vcpu);
|
||||
kvm_reset_pvm_sys_regs(shadow_vcpu);
|
||||
sve_state = kern_hyp_va(shadow_vcpu->arch.sve_state);
|
||||
sve_state_size = vcpu_sve_state_size(shadow_vcpu);
|
||||
|
||||
vm->vcpus[i] = shadow_vcpu;
|
||||
shadow_state->vm = vm;
|
||||
|
||||
shadow_vcpu->arch.hw_mmu = &vm->arch.mmu;
|
||||
shadow_vcpu->arch.pkvm.shadow_vm = vm;
|
||||
shadow_vcpu->arch.power_off = true;
|
||||
|
||||
if (test_bit(KVM_ARM_VCPU_POWER_OFF, shadow_vcpu->arch.features)) {
|
||||
shadow_vcpu->arch.pkvm.power_state = PSCI_0_2_AFFINITY_LEVEL_OFF;
|
||||
} else if (pvm_has_pvmfw(vm)) {
|
||||
if (vm->pvmfw_entry_vcpu)
|
||||
return -EINVAL;
|
||||
|
||||
vm->pvmfw_entry_vcpu = shadow_vcpu;
|
||||
shadow_vcpu->arch.reset_state.reset = true;
|
||||
shadow_vcpu->arch.pkvm.power_state = PSCI_0_2_AFFINITY_LEVEL_ON_PENDING;
|
||||
} else {
|
||||
struct vcpu_reset_state *reset_state = &shadow_vcpu->arch.reset_state;
|
||||
|
||||
reset_state->pc = *vcpu_pc(host_vcpu);
|
||||
reset_state->r0 = vcpu_get_reg(host_vcpu, 0);
|
||||
reset_state->reset = true;
|
||||
shadow_vcpu->arch.pkvm.power_state = PSCI_0_2_AFFINITY_LEVEL_ON_PENDING;
|
||||
if (!shadow_vcpu->arch.sve_state || !sve_state_size ||
|
||||
hyp_pin_shared_mem(sve_state, sve_state + sve_state_size)) {
|
||||
clear_bit(KVM_ARM_VCPU_SVE, shadow_vcpu->arch.features);
|
||||
shadow_vcpu->arch.sve_state = NULL;
|
||||
shadow_vcpu->arch.sve_max_vl = 0;
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (vm->arch.pkvm.enabled)
|
||||
pkvm_vcpu_init_traps(shadow_vcpu);
|
||||
kvm_reset_pvm_sys_regs(shadow_vcpu);
|
||||
|
||||
vm->vcpus[vcpu_idx] = shadow_vcpu;
|
||||
shadow_state->vm = vm;
|
||||
|
||||
shadow_vcpu->arch.hw_mmu = &vm->arch.mmu;
|
||||
shadow_vcpu->arch.pkvm.shadow_vm = vm;
|
||||
shadow_vcpu->arch.power_off = true;
|
||||
|
||||
if (test_bit(KVM_ARM_VCPU_POWER_OFF, shadow_vcpu->arch.features)) {
|
||||
shadow_vcpu->arch.pkvm.power_state =
|
||||
PSCI_0_2_AFFINITY_LEVEL_OFF;
|
||||
} else if (pvm_has_pvmfw(vm)) {
|
||||
if (vm->pvmfw_entry_vcpu) {
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
vm->pvmfw_entry_vcpu = shadow_vcpu;
|
||||
shadow_vcpu->arch.reset_state.reset = true;
|
||||
shadow_vcpu->arch.pkvm.power_state =
|
||||
PSCI_0_2_AFFINITY_LEVEL_ON_PENDING;
|
||||
} else {
|
||||
struct vcpu_reset_state *reset_state =
|
||||
&shadow_vcpu->arch.reset_state;
|
||||
|
||||
reset_state->pc = *vcpu_pc(host_vcpu);
|
||||
reset_state->r0 = vcpu_get_reg(host_vcpu, 0);
|
||||
reset_state->reset = true;
|
||||
shadow_vcpu->arch.pkvm.power_state =
|
||||
PSCI_0_2_AFFINITY_LEVEL_ON_PENDING;
|
||||
}
|
||||
|
||||
done:
|
||||
if (ret)
|
||||
unpin_host_vcpu(shadow_state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool __exists_shadow(struct kvm *host_kvm)
|
||||
@@ -591,7 +591,7 @@ static size_t pkvm_get_shadow_size(int num_vcpus)
|
||||
{
|
||||
/* Shadow space for the vm struct and all of its vcpu states. */
|
||||
return sizeof(struct kvm_shadow_vm) +
|
||||
sizeof(struct shadow_vcpu_state) * num_vcpus;
|
||||
sizeof(struct shadow_vcpu_state *) * num_vcpus;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -613,14 +613,14 @@ static int check_shadow_size(int nr_vcpus, size_t shadow_size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void drain_shadow_vcpus(struct shadow_vcpu_state *shadow_vcpus,
|
||||
static void drain_shadow_vcpus(struct shadow_vcpu_state *shadow_vcpus[],
|
||||
unsigned int nr_vcpus,
|
||||
struct kvm_hyp_memcache *mc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr_vcpus; i++) {
|
||||
struct kvm_vcpu *shadow_vcpu = &shadow_vcpus[i].vcpu;
|
||||
struct kvm_vcpu *shadow_vcpu = &shadow_vcpus[i]->vcpu;
|
||||
struct kvm_hyp_memcache *vcpu_mc = &shadow_vcpu->arch.pkvm_memcache;
|
||||
void *addr;
|
||||
|
||||
@@ -645,8 +645,6 @@ static void drain_shadow_vcpus(struct shadow_vcpu_state *shadow_vcpus,
|
||||
* Must be a multiple of the page size.
|
||||
* pgd: The host va of the area being donated for the stage-2 PGD for the VM.
|
||||
* Must be page aligned. Its size is implied by the VM's VTCR.
|
||||
* Note: An array to the host KVM VCPUs (host VA) is passed via the pgd, as to
|
||||
* not to be dependent on how the VCPU's are layed out in struct kvm.
|
||||
*
|
||||
* Return a unique handle to the protected VM on success,
|
||||
* negative error code on failure.
|
||||
@@ -698,19 +696,13 @@ int __pkvm_init_shadow(struct kvm *kvm,
|
||||
if (ret)
|
||||
goto err_remove_mappings;
|
||||
|
||||
ret = set_host_vcpus(vm->shadow_vcpus, nr_vcpus, pgd, pgd_size);
|
||||
if (ret)
|
||||
goto err_remove_pgd;
|
||||
|
||||
ret = init_shadow_structs(kvm, vm, pgd, nr_vcpus);
|
||||
if (ret < 0)
|
||||
goto err_unpin_host_vcpus;
|
||||
init_shadow_vm(kvm, vm, nr_vcpus);
|
||||
|
||||
/* Add the entry to the shadow table. */
|
||||
hyp_spin_lock(&shadow_lock);
|
||||
ret = insert_shadow_table(kvm, vm, shadow_size);
|
||||
if (ret < 0)
|
||||
goto err_unlock_unpin_host_vcpus;
|
||||
goto err_unlock;
|
||||
|
||||
ret = kvm_guest_prepare_stage2(vm, pgd);
|
||||
if (ret)
|
||||
@@ -721,34 +713,106 @@ int __pkvm_init_shadow(struct kvm *kvm,
|
||||
|
||||
err_remove_shadow_table:
|
||||
remove_shadow_table(vm->shadow_handle);
|
||||
err_unlock_unpin_host_vcpus:
|
||||
err_unlock:
|
||||
hyp_spin_unlock(&shadow_lock);
|
||||
err_unpin_host_vcpus:
|
||||
unpin_host_vcpus(vm->shadow_vcpus, nr_vcpus);
|
||||
err_remove_pgd:
|
||||
WARN_ON(__pkvm_hyp_donate_host(hyp_virt_to_pfn(pgd), nr_pgd_pages));
|
||||
|
||||
err_remove_mappings:
|
||||
/* Clear the donated shadow memory on failure to avoid data leaks. */
|
||||
memset(vm, 0, shadow_size);
|
||||
WARN_ON(__pkvm_hyp_donate_host(hyp_phys_to_pfn(shadow_pa),
|
||||
shadow_size >> PAGE_SHIFT));
|
||||
|
||||
err:
|
||||
hyp_unpin_shared_mem(kvm, kvm + 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the protected vcpu state shadow copy in host-donated memory.
|
||||
*
|
||||
* shadow_handle: The handle for the protected vm.
|
||||
* host_vcpu: A pointer to the corresponding host vcpu (host va).
|
||||
* shadow_vcpu_hva: The host va of the area being donated for the vcpu state.
|
||||
* Must be page aligned. The size of the area must be equal to
|
||||
* the paged-aligned size of kvm_shadow_vcpu_state.
|
||||
*
|
||||
* Return 0 on success, negative error code on failure.
|
||||
*/
|
||||
int __pkvm_init_shadow_vcpu(unsigned int shadow_handle,
|
||||
struct kvm_vcpu *host_vcpu,
|
||||
void *shadow_vcpu_hva)
|
||||
{
|
||||
struct kvm_shadow_vm *vm;
|
||||
struct shadow_vcpu_state *shadow_state = kern_hyp_va(shadow_vcpu_hva);
|
||||
size_t vcpu_state_sz = sizeof(*shadow_state);
|
||||
u64 nr_pages = PAGE_ALIGN(vcpu_state_sz) >> PAGE_SHIFT;
|
||||
unsigned int idx;
|
||||
int ret;
|
||||
|
||||
if (!PAGE_ALIGNED(shadow_vcpu_hva))
|
||||
return -EINVAL;
|
||||
|
||||
ret = __pkvm_host_donate_hyp(hyp_virt_to_pfn(shadow_state),
|
||||
nr_pages);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memset(shadow_state, 0, vcpu_state_sz);
|
||||
|
||||
hyp_spin_lock(&shadow_lock);
|
||||
|
||||
vm = find_shadow_by_handle(shadow_handle);
|
||||
if (!vm) {
|
||||
ret = -ENOENT;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
idx = vm->nr_vcpus;
|
||||
if (idx >= vm->created_vcpus) {
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = init_shadow_vcpu(shadow_state, host_vcpu, vm, idx);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
vm->shadow_vcpus[idx] = shadow_state;
|
||||
vm->nr_vcpus++;
|
||||
unlock:
|
||||
hyp_spin_unlock(&shadow_lock);
|
||||
|
||||
if (ret) {
|
||||
memset(shadow_state, 0, vcpu_state_sz);
|
||||
WARN_ON(__pkvm_hyp_donate_host(hyp_virt_to_pfn(shadow_state),
|
||||
nr_pages));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void teardown_donated_memory(struct kvm_hyp_memcache *mc, void *addr,
|
||||
size_t size)
|
||||
{
|
||||
u64 pfn = hyp_phys_to_pfn(__hyp_pa(addr));
|
||||
u64 nr_pages = size >> PAGE_SHIFT;
|
||||
void *start;
|
||||
|
||||
memset(addr, 0, size);
|
||||
kvm_flush_dcache_to_poc(addr, size);
|
||||
|
||||
for (start = addr; start < addr + size; start += PAGE_SIZE)
|
||||
push_hyp_memcache(mc, start, hyp_virt_to_phys);
|
||||
|
||||
WARN_ON(__pkvm_hyp_donate_host(pfn, nr_pages));
|
||||
}
|
||||
|
||||
int __pkvm_teardown_shadow(int shadow_handle)
|
||||
{
|
||||
struct kvm_hyp_memcache *mc;
|
||||
struct kvm_shadow_vm *vm;
|
||||
struct kvm *host_kvm;
|
||||
size_t shadow_size;
|
||||
unsigned int nr_vcpus;
|
||||
int err;
|
||||
u64 pfn;
|
||||
u64 nr_pages;
|
||||
void *addr;
|
||||
int i;
|
||||
|
||||
/* Lookup then remove entry from the shadow table. */
|
||||
@@ -764,6 +828,9 @@ int __pkvm_teardown_shadow(int shadow_handle)
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
host_kvm = vm->host_kvm;
|
||||
nr_vcpus = vm->nr_vcpus;
|
||||
|
||||
/*
|
||||
* Clear the tracking for last_loaded_vcpu for all cpus for this vm in
|
||||
* case the same addresses for those vcpus are reused for future vms.
|
||||
@@ -783,22 +850,17 @@ int __pkvm_teardown_shadow(int shadow_handle)
|
||||
hyp_spin_unlock(&shadow_lock);
|
||||
|
||||
/* Reclaim guest pages, and page-table pages */
|
||||
mc = &vm->host_kvm->arch.pkvm.teardown_mc;
|
||||
mc = &host_kvm->arch.pkvm.teardown_mc;
|
||||
reclaim_guest_pages(vm, mc);
|
||||
drain_shadow_vcpus(vm->shadow_vcpus, vm->created_vcpus, mc);
|
||||
unpin_host_vcpus(vm->shadow_vcpus, vm->created_vcpus);
|
||||
drain_shadow_vcpus(vm->shadow_vcpus, nr_vcpus, mc);
|
||||
unpin_host_vcpus(vm->shadow_vcpus, nr_vcpus);
|
||||
|
||||
for (i = 0; i < nr_vcpus; i++)
|
||||
teardown_donated_memory(mc, vm->shadow_vcpus[i],
|
||||
PAGE_ALIGN(sizeof(vm->shadow_vcpus[i])));
|
||||
teardown_donated_memory(mc, vm, vm->shadow_area_size);
|
||||
|
||||
/* Push the metadata pages to the teardown memcache */
|
||||
shadow_size = vm->shadow_area_size;
|
||||
host_kvm = vm->host_kvm;
|
||||
memset(vm, 0, shadow_size);
|
||||
for (addr = vm; addr < ((void *)vm + shadow_size); addr += PAGE_SIZE)
|
||||
push_hyp_memcache(mc, addr, hyp_virt_to_phys);
|
||||
hyp_unpin_shared_mem(host_kvm, host_kvm + 1);
|
||||
|
||||
pfn = hyp_phys_to_pfn(__hyp_pa(vm));
|
||||
nr_pages = shadow_size >> PAGE_SHIFT;
|
||||
WARN_ON(__pkvm_hyp_donate_host(pfn, nr_pages));
|
||||
return 0;
|
||||
|
||||
err_unlock:
|
||||
@@ -919,7 +981,7 @@ struct kvm_vcpu *pvm_mpidr_to_vcpu(struct kvm_shadow_vm *vm, unsigned long mpidr
|
||||
|
||||
mpidr &= MPIDR_HWID_BITMASK;
|
||||
|
||||
for (i = 0; i < vm->created_vcpus; i++) {
|
||||
for (i = 0; i < READ_ONCE(vm->nr_vcpus); i++) {
|
||||
vcpu = vm->vcpus[i];
|
||||
|
||||
if (mpidr == kvm_vcpu_get_mpidr_aff(vcpu))
|
||||
@@ -1036,7 +1098,7 @@ static bool pvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu)
|
||||
* then if at least one is PENDING_ON then return PENDING_ON.
|
||||
* Otherwise, return OFF.
|
||||
*/
|
||||
for (i = 0; i < vm->created_vcpus; i++) {
|
||||
for (i = 0; i < READ_ONCE(vm->nr_vcpus); i++) {
|
||||
tmp = vm->vcpus[i];
|
||||
mpidr = kvm_vcpu_get_mpidr_aff(tmp);
|
||||
|
||||
@@ -1246,7 +1308,7 @@ out_guest_err:
|
||||
|
||||
static bool pkvm_install_ioguard_page(struct kvm_vcpu *vcpu, u64 *exit_code)
|
||||
{
|
||||
u32 retval = SMCCC_RET_SUCCESS;
|
||||
u64 retval = SMCCC_RET_SUCCESS;
|
||||
u64 ipa = smccc_get_arg1(vcpu);
|
||||
int ret;
|
||||
|
||||
@@ -1338,6 +1400,8 @@ bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code)
|
||||
return pkvm_install_ioguard_page(vcpu, exit_code);
|
||||
case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_UNMAP_FUNC_ID:
|
||||
if (__pkvm_remove_ioguard_page(vcpu, vcpu_get_reg(vcpu, 1)))
|
||||
val[0] = SMCCC_RET_INVALID_PARAMETER;
|
||||
else
|
||||
val[0] = SMCCC_RET_SUCCESS;
|
||||
break;
|
||||
case ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_INFO_FUNC_ID:
|
||||
|
||||
@@ -235,7 +235,7 @@ static u64 psci_mem_protect(s64 offset)
|
||||
return cnt;
|
||||
|
||||
if (!cnt || !new)
|
||||
psci_call(PSCI_1_1_FN64_MEM_PROTECT, offset < 0 ? 0 : 1, 0, 0);
|
||||
psci_call(PSCI_1_1_FN_MEM_PROTECT, offset < 0 ? 0 : 1, 0, 0);
|
||||
|
||||
cnt = new;
|
||||
return cnt;
|
||||
@@ -307,10 +307,8 @@ static unsigned long psci_1_0_handler(u64 func_id, struct kvm_cpu_context *host_
|
||||
case PSCI_1_1_FN64_SYSTEM_RESET2:
|
||||
pkvm_clear_pvmfw_pages();
|
||||
hyp_spin_lock(&mem_protect_lock);
|
||||
if (psci_mem_protect_active()) {
|
||||
return psci_0_2_handler(PSCI_0_2_FN_SYSTEM_RESET,
|
||||
host_ctxt);
|
||||
}
|
||||
if (psci_mem_protect_active())
|
||||
cpu_reg(host_ctxt, 0) = PSCI_0_2_FN_SYSTEM_RESET;
|
||||
fallthrough;
|
||||
case PSCI_1_0_FN_PSCI_FEATURES:
|
||||
case PSCI_1_0_FN_SET_SUSPEND_MODE:
|
||||
|
||||
@@ -120,7 +120,7 @@ static void __hyp_vgic_restore_state(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Disable host events, enable guest events
|
||||
*/
|
||||
static bool __pmu_switch_to_guest(struct kvm_cpu_context *host_ctxt)
|
||||
@@ -140,7 +140,7 @@ static bool __pmu_switch_to_guest(struct kvm_cpu_context *host_ctxt)
|
||||
return (pmu->events_host || pmu->events_guest);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Disable guest events, enable host events
|
||||
*/
|
||||
static void __pmu_switch_to_host(struct kvm_cpu_context *host_ctxt)
|
||||
@@ -158,7 +158,7 @@ static void __pmu_switch_to_host(struct kvm_cpu_context *host_ctxt)
|
||||
write_sysreg(pmu->events_host, pmcntenset_el0);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Handler for protected VM MSR, MRS or System instruction execution in AArch64.
|
||||
*
|
||||
* Returns true if the hypervisor has handled the exit, and control should go
|
||||
@@ -175,7 +175,7 @@ static bool kvm_handle_pvm_sys64(struct kvm_vcpu *vcpu, u64 *exit_code)
|
||||
kvm_handle_pvm_sysreg(vcpu, exit_code));
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Handler for protected floating-point and Advanced SIMD accesses.
|
||||
*
|
||||
* Returns true if the hypervisor has handled the exit, and control should go
|
||||
|
||||
@@ -120,8 +120,8 @@ void __init kvm_hyp_reserve(void)
|
||||
*/
|
||||
static int __create_el2_shadow(struct kvm *kvm)
|
||||
{
|
||||
struct kvm_vcpu *vcpu, **vcpu_array;
|
||||
size_t pgd_sz, shadow_sz;
|
||||
struct kvm_vcpu *vcpu;
|
||||
size_t pgd_sz, shadow_sz, vcpu_state_sz;
|
||||
void *pgd, *shadow_addr;
|
||||
unsigned long idx;
|
||||
int shadow_handle;
|
||||
@@ -140,21 +140,15 @@ static int __create_el2_shadow(struct kvm *kvm)
|
||||
if (!pgd)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Allocate memory to donate to hyp for the kvm and vcpu state. */
|
||||
/* Allocate memory to donate to hyp for the kvm and vcpu state pointers. */
|
||||
shadow_sz = PAGE_ALIGN(KVM_SHADOW_VM_SIZE +
|
||||
SHADOW_VCPU_STATE_SIZE * kvm->created_vcpus);
|
||||
sizeof(void *) * kvm->created_vcpus);
|
||||
shadow_addr = alloc_pages_exact(shadow_sz, GFP_KERNEL_ACCOUNT);
|
||||
if (!shadow_addr) {
|
||||
ret = -ENOMEM;
|
||||
goto free_pgd;
|
||||
}
|
||||
|
||||
/* Stash the vcpu pointers into the PGD */
|
||||
BUILD_BUG_ON(KVM_MAX_VCPUS > (PAGE_SIZE / sizeof(u64)));
|
||||
vcpu_array = pgd;
|
||||
kvm_for_each_vcpu(idx, vcpu, kvm)
|
||||
vcpu_array[idx] = vcpu;
|
||||
|
||||
/* Donate the shadow memory to hyp and let hyp initialize it. */
|
||||
ret = kvm_call_hyp_nvhe(__pkvm_init_shadow, kvm, shadow_addr, shadow_sz,
|
||||
pgd);
|
||||
@@ -166,8 +160,35 @@ static int __create_el2_shadow(struct kvm *kvm)
|
||||
/* Store the shadow handle given by hyp for future call reference. */
|
||||
kvm->arch.pkvm.shadow_handle = shadow_handle;
|
||||
|
||||
/* Donate memory for the vcpu state at hyp and initialize it. */
|
||||
vcpu_state_sz = PAGE_ALIGN(SHADOW_VCPU_STATE_SIZE);
|
||||
kvm_for_each_vcpu (idx, vcpu, kvm) {
|
||||
void *vcpu_state;
|
||||
|
||||
/* Indexing of the vcpus to be sequential starting at 0. */
|
||||
if (WARN_ON(vcpu->vcpu_idx != idx)) {
|
||||
ret = -EINVAL;
|
||||
goto destroy_vm;
|
||||
}
|
||||
vcpu_state = alloc_pages_exact(vcpu_state_sz, GFP_KERNEL_ACCOUNT);
|
||||
if (!vcpu_state) {
|
||||
ret = -ENOMEM;
|
||||
goto destroy_vm;
|
||||
}
|
||||
|
||||
ret = kvm_call_hyp_nvhe(__pkvm_init_shadow_vcpu, shadow_handle,
|
||||
vcpu, vcpu_state);
|
||||
if (ret) {
|
||||
free_pages_exact(vcpu_state, vcpu_state_sz);
|
||||
goto destroy_vm;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
destroy_vm:
|
||||
kvm_shadow_destroy(kvm);
|
||||
return ret;
|
||||
free_shadow:
|
||||
free_pages_exact(shadow_addr, shadow_sz);
|
||||
free_pgd:
|
||||
|
||||
@@ -188,15 +188,11 @@ static void kvm_psci_system_reset2(struct kvm_vcpu *vcpu)
|
||||
|
||||
static unsigned long kvm_psci_check_allowed_function(struct kvm_vcpu *vcpu, u32 fn)
|
||||
{
|
||||
switch(fn) {
|
||||
case PSCI_0_2_FN64_CPU_SUSPEND:
|
||||
case PSCI_0_2_FN64_CPU_ON:
|
||||
case PSCI_0_2_FN64_AFFINITY_INFO:
|
||||
/* Disallow these functions for 32bit guests */
|
||||
if (vcpu_mode_is_32bit(vcpu))
|
||||
return PSCI_RET_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Prevent 32 bit guests from calling 64 bit PSCI functions.
|
||||
*/
|
||||
if ((fn & PSCI_0_2_64BIT) && vcpu_mode_is_32bit(vcpu))
|
||||
return PSCI_RET_NOT_SUPPORTED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -208,10 +204,6 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
|
||||
unsigned long val;
|
||||
int ret = 1;
|
||||
|
||||
val = kvm_psci_check_allowed_function(vcpu, psci_fn);
|
||||
if (val)
|
||||
goto out;
|
||||
|
||||
switch (psci_fn) {
|
||||
case PSCI_0_2_FN_PSCI_VERSION:
|
||||
/*
|
||||
@@ -279,7 +271,6 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
smccc_set_retval(vcpu, val, 0, 0, 0);
|
||||
return ret;
|
||||
}
|
||||
@@ -399,6 +390,15 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
|
||||
*/
|
||||
int kvm_psci_call(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
u32 psci_fn = smccc_get_function(vcpu);
|
||||
unsigned long val;
|
||||
|
||||
val = kvm_psci_check_allowed_function(vcpu, psci_fn);
|
||||
if (val) {
|
||||
smccc_set_retval(vcpu, val, 0, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (kvm_psci_version(vcpu, vcpu->kvm)) {
|
||||
case KVM_ARM_PSCI_1_1:
|
||||
return kvm_psci_1_x_call(vcpu, 1);
|
||||
|
||||
@@ -1048,8 +1048,7 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu,
|
||||
val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_CSV2), (u64)vcpu->kvm->arch.pfr0_csv2);
|
||||
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_CSV3);
|
||||
val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_CSV3), (u64)vcpu->kvm->arch.pfr0_csv3);
|
||||
if (irqchip_in_kernel(vcpu->kvm) &&
|
||||
vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
|
||||
if (kvm_vgic_global_state.type == VGIC_V3) {
|
||||
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_GIC);
|
||||
val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_GIC), 1);
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ config X86
|
||||
select ARCH_HAS_PMEM_API if X86_64
|
||||
select ARCH_HAS_PTE_DEVMAP if X86_64
|
||||
select ARCH_HAS_PTE_SPECIAL
|
||||
select ARCH_HAS_NONLEAF_PMD_YOUNG
|
||||
select ARCH_HAS_NONLEAF_PMD_YOUNG if PGTABLE_LEVELS > 2
|
||||
select ARCH_HAS_UACCESS_FLUSHCACHE if X86_64
|
||||
select ARCH_HAS_COPY_MC if X86_64
|
||||
select ARCH_HAS_SET_MEMORY
|
||||
|
||||
@@ -462,6 +462,7 @@ CONFIG_USB_CONFIGFS_F_ACC=y
|
||||
CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
|
||||
CONFIG_USB_CONFIGFS_F_MIDI=y
|
||||
CONFIG_USB_CONFIGFS_F_HID=y
|
||||
CONFIG_USB_CONFIGFS_F_UVC=y
|
||||
CONFIG_TYPEC=y
|
||||
CONFIG_TYPEC_TCPM=y
|
||||
CONFIG_TYPEC_TCPCI=y
|
||||
|
||||
@@ -737,6 +737,7 @@ static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||
|
||||
if (at_head) {
|
||||
list_add(&rq->queuelist, &per_prio->dispatch);
|
||||
rq->fifo_time = jiffies;
|
||||
} else {
|
||||
deadline_add_rq_rb(per_prio, rq);
|
||||
|
||||
|
||||
@@ -13,11 +13,13 @@ KMI_SYMBOL_LIST=android/abi_gki_aarch64
|
||||
ADDITIONAL_KMI_SYMBOL_LISTS="
|
||||
android/abi_gki_aarch64_type_visibility
|
||||
android/abi_gki_aarch64_core
|
||||
android/abi_gki_aarch64_exynos
|
||||
android/abi_gki_aarch64_fips140
|
||||
android/abi_gki_aarch64_generic
|
||||
android/abi_gki_aarch64_virtual_device
|
||||
android/abi_gki_aarch64_db845c
|
||||
android/abi_gki_aarch64_hikey960
|
||||
android/abi_gki_aarch64_rockchip
|
||||
"
|
||||
|
||||
FILES="${FILES}
|
||||
|
||||
8
build.config.rockchip
Normal file
8
build.config.rockchip
Normal file
@@ -0,0 +1,8 @@
|
||||
. ${ROOT_DIR}/${KERNEL_DIR}/build.config.gki.aarch64
|
||||
|
||||
|
||||
DEFCONFIG=rockchip_aarch64_gki_defconfig
|
||||
KMI_SYMBOL_LIST=android/abi_gki_aarch64_rockchip
|
||||
PRE_DEFCONFIG_CMDS="KCONFIG_CONFIG=${ROOT_DIR}/common/arch/arm64/configs/${DEFCONFIG} ${ROOT_DIR}/common/scripts/kconfig/merge_config.sh -m -r ${ROOT_DIR}/common/arch/arm64/configs/gki_defconfig ${ROOT_DIR}/common/arch/arm64/configs/rockchip_gki.fragment"
|
||||
POST_DEFCONFIG_CMDS="rm ${ROOT_DIR}/common/arch/arm64/configs/${DEFCONFIG}"
|
||||
|
||||
@@ -211,7 +211,7 @@ UBSAN_SANITIZE_jitterentropy-fips.o = n
|
||||
# module that is in scope for FIPS 140-2 certification
|
||||
#
|
||||
crypto-fips-objs := drbg.o ecb.o cbc.o ctr.o cts.o gcm.o xts.o hmac.o cmac.o \
|
||||
memneq.o gf128mul.o aes_generic.o lib-crypto-aes.o \
|
||||
gf128mul.o aes_generic.o lib-crypto-aes.o \
|
||||
jitterentropy.o jitterentropy-kcapi.o \
|
||||
sha1_generic.o sha256_generic.o sha512_generic.o \
|
||||
lib-sha1.o lib-crypto-sha256.o
|
||||
|
||||
@@ -117,6 +117,22 @@ struct rand_data {
|
||||
#define JENT_EHEALTH 9 /* Health test failed during initialization */
|
||||
#define JENT_ERCT 10 /* RCT failed during initialization */
|
||||
|
||||
/*
|
||||
* The output n bits can receive more than n bits of min entropy, of course,
|
||||
* but the fixed output of the conditioning function can only asymptotically
|
||||
* approach the output size bits of min entropy, not attain that bound. Random
|
||||
* maps will tend to have output collisions, which reduces the creditable
|
||||
* output entropy (that is what SP 800-90B Section 3.1.5.1.2 attempts to bound).
|
||||
*
|
||||
* The value "64" is justified in Appendix A.4 of the current 90C draft,
|
||||
* and aligns with NIST's in "epsilon" definition in this document, which is
|
||||
* that a string can be considered "full entropy" if you can bound the min
|
||||
* entropy in each bit of output to at least 1-epsilon, where epsilon is
|
||||
* required to be <= 2^(-32).
|
||||
*/
|
||||
#define JENT_ENTROPY_SAFETY_FACTOR 64
|
||||
|
||||
#include <linux/fips.h>
|
||||
#include "jitterentropy.h"
|
||||
|
||||
/***************************************************************************
|
||||
@@ -546,7 +562,10 @@ static int jent_measure_jitter(struct rand_data *ec)
|
||||
*/
|
||||
static void jent_gen_entropy(struct rand_data *ec)
|
||||
{
|
||||
unsigned int k = 0;
|
||||
unsigned int k = 0, safety_factor = 0;
|
||||
|
||||
if (fips_enabled)
|
||||
safety_factor = JENT_ENTROPY_SAFETY_FACTOR;
|
||||
|
||||
/* priming of the ->prev_time value */
|
||||
jent_measure_jitter(ec);
|
||||
@@ -560,7 +579,7 @@ static void jent_gen_entropy(struct rand_data *ec)
|
||||
* We multiply the loop value with ->osr to obtain the
|
||||
* oversampling rate requested by the caller
|
||||
*/
|
||||
if (++k >= (DATA_SIZE_BITS * ec->osr))
|
||||
if (++k >= ((DATA_SIZE_BITS + safety_factor) * ec->osr))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1813,15 +1813,21 @@ static void binder_cleanup_transaction(struct binder_transaction *t,
|
||||
/**
|
||||
* binder_get_object() - gets object and checks for valid metadata
|
||||
* @proc: binder_proc owning the buffer
|
||||
* @u: sender's user pointer to base of buffer
|
||||
* @buffer: binder_buffer that we're parsing.
|
||||
* @offset: offset in the @buffer at which to validate an object.
|
||||
* @object: struct binder_object to read into
|
||||
*
|
||||
* Return: If there's a valid metadata object at @offset in @buffer, the
|
||||
* Copy the binder object at the given offset into @object. If @u is
|
||||
* provided then the copy is from the sender's buffer. If not, then
|
||||
* it is copied from the target's @buffer.
|
||||
*
|
||||
* Return: If there's a valid metadata object at @offset, the
|
||||
* size of that object. Otherwise, it returns zero. The object
|
||||
* is read into the struct binder_object pointed to by @object.
|
||||
*/
|
||||
static size_t binder_get_object(struct binder_proc *proc,
|
||||
const void __user *u,
|
||||
struct binder_buffer *buffer,
|
||||
unsigned long offset,
|
||||
struct binder_object *object)
|
||||
@@ -1831,10 +1837,16 @@ static size_t binder_get_object(struct binder_proc *proc,
|
||||
size_t object_size = 0;
|
||||
|
||||
read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
|
||||
if (offset > buffer->data_size || read_size < sizeof(*hdr) ||
|
||||
binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
|
||||
offset, read_size))
|
||||
if (offset > buffer->data_size || read_size < sizeof(*hdr))
|
||||
return 0;
|
||||
if (u) {
|
||||
if (copy_from_user(object, u + offset, read_size))
|
||||
return 0;
|
||||
} else {
|
||||
if (binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
|
||||
offset, read_size))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ok, now see if we read a complete object. */
|
||||
hdr = &object->hdr;
|
||||
@@ -1907,7 +1919,7 @@ static struct binder_buffer_object *binder_validate_ptr(
|
||||
b, buffer_offset,
|
||||
sizeof(object_offset)))
|
||||
return NULL;
|
||||
object_size = binder_get_object(proc, b, object_offset, object);
|
||||
object_size = binder_get_object(proc, NULL, b, object_offset, object);
|
||||
if (!object_size || object->hdr.type != BINDER_TYPE_PTR)
|
||||
return NULL;
|
||||
if (object_offsetp)
|
||||
@@ -1972,7 +1984,8 @@ static bool binder_validate_fixup(struct binder_proc *proc,
|
||||
unsigned long buffer_offset;
|
||||
struct binder_object last_object;
|
||||
struct binder_buffer_object *last_bbo;
|
||||
size_t object_size = binder_get_object(proc, b, last_obj_offset,
|
||||
size_t object_size = binder_get_object(proc, NULL, b,
|
||||
last_obj_offset,
|
||||
&last_object);
|
||||
if (object_size != sizeof(*last_bbo))
|
||||
return false;
|
||||
@@ -2087,7 +2100,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
|
||||
if (!binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
|
||||
buffer, buffer_offset,
|
||||
sizeof(object_offset)))
|
||||
object_size = binder_get_object(proc, buffer,
|
||||
object_size = binder_get_object(proc, NULL, buffer,
|
||||
object_offset, &object);
|
||||
if (object_size == 0) {
|
||||
pr_err("transaction release %d bad object at offset %lld, size %zd\n",
|
||||
@@ -2425,16 +2438,266 @@ err_fd_not_accepted:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int binder_translate_fd_array(struct binder_fd_array_object *fda,
|
||||
/**
|
||||
* struct binder_ptr_fixup - data to be fixed-up in target buffer
|
||||
* @offset offset in target buffer to fixup
|
||||
* @skip_size bytes to skip in copy (fixup will be written later)
|
||||
* @fixup_data data to write at fixup offset
|
||||
* @node list node
|
||||
*
|
||||
* This is used for the pointer fixup list (pf) which is created and consumed
|
||||
* during binder_transaction() and is only accessed locally. No
|
||||
* locking is necessary.
|
||||
*
|
||||
* The list is ordered by @offset.
|
||||
*/
|
||||
struct binder_ptr_fixup {
|
||||
binder_size_t offset;
|
||||
size_t skip_size;
|
||||
binder_uintptr_t fixup_data;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct binder_sg_copy - scatter-gather data to be copied
|
||||
* @offset offset in target buffer
|
||||
* @sender_uaddr user address in source buffer
|
||||
* @length bytes to copy
|
||||
* @node list node
|
||||
*
|
||||
* This is used for the sg copy list (sgc) which is created and consumed
|
||||
* during binder_transaction() and is only accessed locally. No
|
||||
* locking is necessary.
|
||||
*
|
||||
* The list is ordered by @offset.
|
||||
*/
|
||||
struct binder_sg_copy {
|
||||
binder_size_t offset;
|
||||
const void __user *sender_uaddr;
|
||||
size_t length;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
/**
|
||||
* binder_do_deferred_txn_copies() - copy and fixup scatter-gather data
|
||||
* @alloc: binder_alloc associated with @buffer
|
||||
* @buffer: binder buffer in target process
|
||||
* @sgc_head: list_head of scatter-gather copy list
|
||||
* @pf_head: list_head of pointer fixup list
|
||||
*
|
||||
* Processes all elements of @sgc_head, applying fixups from @pf_head
|
||||
* and copying the scatter-gather data from the source process' user
|
||||
* buffer to the target's buffer. It is expected that the list creation
|
||||
* and processing all occurs during binder_transaction() so these lists
|
||||
* are only accessed in local context.
|
||||
*
|
||||
* Return: 0=success, else -errno
|
||||
*/
|
||||
static int binder_do_deferred_txn_copies(struct binder_alloc *alloc,
|
||||
struct binder_buffer *buffer,
|
||||
struct list_head *sgc_head,
|
||||
struct list_head *pf_head)
|
||||
{
|
||||
int ret = 0;
|
||||
struct binder_sg_copy *sgc, *tmpsgc;
|
||||
struct binder_ptr_fixup *tmppf;
|
||||
struct binder_ptr_fixup *pf =
|
||||
list_first_entry_or_null(pf_head, struct binder_ptr_fixup,
|
||||
node);
|
||||
|
||||
list_for_each_entry_safe(sgc, tmpsgc, sgc_head, node) {
|
||||
size_t bytes_copied = 0;
|
||||
|
||||
while (bytes_copied < sgc->length) {
|
||||
size_t copy_size;
|
||||
size_t bytes_left = sgc->length - bytes_copied;
|
||||
size_t offset = sgc->offset + bytes_copied;
|
||||
|
||||
/*
|
||||
* We copy up to the fixup (pointed to by pf)
|
||||
*/
|
||||
copy_size = pf ? min(bytes_left, (size_t)pf->offset - offset)
|
||||
: bytes_left;
|
||||
if (!ret && copy_size)
|
||||
ret = binder_alloc_copy_user_to_buffer(
|
||||
alloc, buffer,
|
||||
offset,
|
||||
sgc->sender_uaddr + bytes_copied,
|
||||
copy_size);
|
||||
bytes_copied += copy_size;
|
||||
if (copy_size != bytes_left) {
|
||||
BUG_ON(!pf);
|
||||
/* we stopped at a fixup offset */
|
||||
if (pf->skip_size) {
|
||||
/*
|
||||
* we are just skipping. This is for
|
||||
* BINDER_TYPE_FDA where the translated
|
||||
* fds will be fixed up when we get
|
||||
* to target context.
|
||||
*/
|
||||
bytes_copied += pf->skip_size;
|
||||
} else {
|
||||
/* apply the fixup indicated by pf */
|
||||
if (!ret)
|
||||
ret = binder_alloc_copy_to_buffer(
|
||||
alloc, buffer,
|
||||
pf->offset,
|
||||
&pf->fixup_data,
|
||||
sizeof(pf->fixup_data));
|
||||
bytes_copied += sizeof(pf->fixup_data);
|
||||
}
|
||||
list_del(&pf->node);
|
||||
kfree(pf);
|
||||
pf = list_first_entry_or_null(pf_head,
|
||||
struct binder_ptr_fixup, node);
|
||||
}
|
||||
}
|
||||
list_del(&sgc->node);
|
||||
kfree(sgc);
|
||||
}
|
||||
list_for_each_entry_safe(pf, tmppf, pf_head, node) {
|
||||
BUG_ON(pf->skip_size == 0);
|
||||
list_del(&pf->node);
|
||||
kfree(pf);
|
||||
}
|
||||
BUG_ON(!list_empty(sgc_head));
|
||||
|
||||
return ret > 0 ? -EINVAL : ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* binder_cleanup_deferred_txn_lists() - free specified lists
|
||||
* @sgc_head: list_head of scatter-gather copy list
|
||||
* @pf_head: list_head of pointer fixup list
|
||||
*
|
||||
* Called to clean up @sgc_head and @pf_head if there is an
|
||||
* error.
|
||||
*/
|
||||
static void binder_cleanup_deferred_txn_lists(struct list_head *sgc_head,
|
||||
struct list_head *pf_head)
|
||||
{
|
||||
struct binder_sg_copy *sgc, *tmpsgc;
|
||||
struct binder_ptr_fixup *pf, *tmppf;
|
||||
|
||||
list_for_each_entry_safe(sgc, tmpsgc, sgc_head, node) {
|
||||
list_del(&sgc->node);
|
||||
kfree(sgc);
|
||||
}
|
||||
list_for_each_entry_safe(pf, tmppf, pf_head, node) {
|
||||
list_del(&pf->node);
|
||||
kfree(pf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* binder_defer_copy() - queue a scatter-gather buffer for copy
|
||||
* @sgc_head: list_head of scatter-gather copy list
|
||||
* @offset: binder buffer offset in target process
|
||||
* @sender_uaddr: user address in source process
|
||||
* @length: bytes to copy
|
||||
*
|
||||
* Specify a scatter-gather block to be copied. The actual copy must
|
||||
* be deferred until all the needed fixups are identified and queued.
|
||||
* Then the copy and fixups are done together so un-translated values
|
||||
* from the source are never visible in the target buffer.
|
||||
*
|
||||
* We are guaranteed that repeated calls to this function will have
|
||||
* monotonically increasing @offset values so the list will naturally
|
||||
* be ordered.
|
||||
*
|
||||
* Return: 0=success, else -errno
|
||||
*/
|
||||
static int binder_defer_copy(struct list_head *sgc_head, binder_size_t offset,
|
||||
const void __user *sender_uaddr, size_t length)
|
||||
{
|
||||
struct binder_sg_copy *bc = kzalloc(sizeof(*bc), GFP_KERNEL);
|
||||
|
||||
if (!bc)
|
||||
return -ENOMEM;
|
||||
|
||||
bc->offset = offset;
|
||||
bc->sender_uaddr = sender_uaddr;
|
||||
bc->length = length;
|
||||
INIT_LIST_HEAD(&bc->node);
|
||||
|
||||
/*
|
||||
* We are guaranteed that the deferred copies are in-order
|
||||
* so just add to the tail.
|
||||
*/
|
||||
list_add_tail(&bc->node, sgc_head);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* binder_add_fixup() - queue a fixup to be applied to sg copy
|
||||
* @pf_head: list_head of binder ptr fixup list
|
||||
* @offset: binder buffer offset in target process
|
||||
* @fixup: bytes to be copied for fixup
|
||||
* @skip_size: bytes to skip when copying (fixup will be applied later)
|
||||
*
|
||||
* Add the specified fixup to a list ordered by @offset. When copying
|
||||
* the scatter-gather buffers, the fixup will be copied instead of
|
||||
* data from the source buffer. For BINDER_TYPE_FDA fixups, the fixup
|
||||
* will be applied later (in target process context), so we just skip
|
||||
* the bytes specified by @skip_size. If @skip_size is 0, we copy the
|
||||
* value in @fixup.
|
||||
*
|
||||
* This function is called *mostly* in @offset order, but there are
|
||||
* exceptions. Since out-of-order inserts are relatively uncommon,
|
||||
* we insert the new element by searching backward from the tail of
|
||||
* the list.
|
||||
*
|
||||
* Return: 0=success, else -errno
|
||||
*/
|
||||
static int binder_add_fixup(struct list_head *pf_head, binder_size_t offset,
|
||||
binder_uintptr_t fixup, size_t skip_size)
|
||||
{
|
||||
struct binder_ptr_fixup *pf = kzalloc(sizeof(*pf), GFP_KERNEL);
|
||||
struct binder_ptr_fixup *tmppf;
|
||||
|
||||
if (!pf)
|
||||
return -ENOMEM;
|
||||
|
||||
pf->offset = offset;
|
||||
pf->fixup_data = fixup;
|
||||
pf->skip_size = skip_size;
|
||||
INIT_LIST_HEAD(&pf->node);
|
||||
|
||||
/* Fixups are *mostly* added in-order, but there are some
|
||||
* exceptions. Look backwards through list for insertion point.
|
||||
*/
|
||||
list_for_each_entry_reverse(tmppf, pf_head, node) {
|
||||
if (tmppf->offset < pf->offset) {
|
||||
list_add(&pf->node, &tmppf->node);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* if we get here, then the new offset is the lowest so
|
||||
* insert at the head
|
||||
*/
|
||||
list_add(&pf->node, pf_head);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int binder_translate_fd_array(struct list_head *pf_head,
|
||||
struct binder_fd_array_object *fda,
|
||||
const void __user *sender_ubuffer,
|
||||
struct binder_buffer_object *parent,
|
||||
struct binder_buffer_object *sender_uparent,
|
||||
struct binder_transaction *t,
|
||||
struct binder_thread *thread,
|
||||
struct binder_transaction *in_reply_to)
|
||||
{
|
||||
binder_size_t fdi, fd_buf_size;
|
||||
binder_size_t fda_offset;
|
||||
const void __user *sender_ufda_base;
|
||||
struct binder_proc *proc = thread->proc;
|
||||
struct binder_proc *target_proc = t->to_proc;
|
||||
int ret;
|
||||
|
||||
if (fda->num_fds == 0)
|
||||
return 0;
|
||||
|
||||
fd_buf_size = sizeof(u32) * fda->num_fds;
|
||||
if (fda->num_fds >= SIZE_MAX / sizeof(u32)) {
|
||||
@@ -2458,19 +2721,25 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
|
||||
*/
|
||||
fda_offset = (parent->buffer - (uintptr_t)t->buffer->user_data) +
|
||||
fda->parent_offset;
|
||||
if (!IS_ALIGNED((unsigned long)fda_offset, sizeof(u32))) {
|
||||
sender_ufda_base = (void __user *)(uintptr_t)sender_uparent->buffer +
|
||||
fda->parent_offset;
|
||||
|
||||
if (!IS_ALIGNED((unsigned long)fda_offset, sizeof(u32)) ||
|
||||
!IS_ALIGNED((unsigned long)sender_ufda_base, sizeof(u32))) {
|
||||
binder_user_error("%d:%d parent offset not aligned correctly.\n",
|
||||
proc->pid, thread->pid);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = binder_add_fixup(pf_head, fda_offset, 0, fda->num_fds * sizeof(u32));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (fdi = 0; fdi < fda->num_fds; fdi++) {
|
||||
u32 fd;
|
||||
int ret;
|
||||
binder_size_t offset = fda_offset + fdi * sizeof(fd);
|
||||
binder_size_t sender_uoffset = fdi * sizeof(fd);
|
||||
|
||||
ret = binder_alloc_copy_from_buffer(&target_proc->alloc,
|
||||
&fd, t->buffer,
|
||||
offset, sizeof(fd));
|
||||
ret = copy_from_user(&fd, sender_ufda_base + sender_uoffset, sizeof(fd));
|
||||
if (!ret)
|
||||
ret = binder_translate_fd(fd, offset, t, thread,
|
||||
in_reply_to);
|
||||
@@ -2480,7 +2749,8 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int binder_fixup_parent(struct binder_transaction *t,
|
||||
static int binder_fixup_parent(struct list_head *pf_head,
|
||||
struct binder_transaction *t,
|
||||
struct binder_thread *thread,
|
||||
struct binder_buffer_object *bp,
|
||||
binder_size_t off_start_offset,
|
||||
@@ -2526,14 +2796,7 @@ static int binder_fixup_parent(struct binder_transaction *t,
|
||||
}
|
||||
buffer_offset = bp->parent_offset +
|
||||
(uintptr_t)parent->buffer - (uintptr_t)b->user_data;
|
||||
if (binder_alloc_copy_to_buffer(&target_proc->alloc, b, buffer_offset,
|
||||
&bp->buffer, sizeof(bp->buffer))) {
|
||||
binder_user_error("%d:%d got transaction with invalid parent offset\n",
|
||||
proc->pid, thread->pid);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return binder_add_fixup(pf_head, buffer_offset, bp->buffer, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2744,6 +3007,7 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
binder_size_t off_start_offset, off_end_offset;
|
||||
binder_size_t off_min;
|
||||
binder_size_t sg_buf_offset, sg_buf_end_offset;
|
||||
binder_size_t user_offset = 0;
|
||||
struct binder_proc *target_proc = NULL;
|
||||
struct binder_thread *target_thread = NULL;
|
||||
struct binder_node *target_node = NULL;
|
||||
@@ -2759,6 +3023,12 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
char *secctx = NULL;
|
||||
u32 secctx_sz = 0;
|
||||
bool is_nested = false;
|
||||
struct list_head sgc_head;
|
||||
struct list_head pf_head;
|
||||
const void __user *user_buffer = (const void __user *)
|
||||
(uintptr_t)tr->data.ptr.buffer;
|
||||
INIT_LIST_HEAD(&sgc_head);
|
||||
INIT_LIST_HEAD(&pf_head);
|
||||
|
||||
e = binder_transaction_log_add(&binder_transaction_log);
|
||||
e->debug_id = t_debug_id;
|
||||
@@ -3101,19 +3371,6 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
t->buffer->clear_on_free = !!(t->flags & TF_CLEAR_BUF);
|
||||
trace_binder_transaction_alloc_buf(t->buffer);
|
||||
|
||||
if (binder_alloc_copy_user_to_buffer(
|
||||
&target_proc->alloc,
|
||||
t->buffer, 0,
|
||||
(const void __user *)
|
||||
(uintptr_t)tr->data.ptr.buffer,
|
||||
tr->data_size)) {
|
||||
binder_user_error("%d:%d got transaction with invalid data ptr\n",
|
||||
proc->pid, thread->pid);
|
||||
return_error = BR_FAILED_REPLY;
|
||||
return_error_param = -EFAULT;
|
||||
return_error_line = __LINE__;
|
||||
goto err_copy_data_failed;
|
||||
}
|
||||
if (binder_alloc_copy_user_to_buffer(
|
||||
&target_proc->alloc,
|
||||
t->buffer,
|
||||
@@ -3158,6 +3415,7 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
size_t object_size;
|
||||
struct binder_object object;
|
||||
binder_size_t object_offset;
|
||||
binder_size_t copy_size;
|
||||
|
||||
if (binder_alloc_copy_from_buffer(&target_proc->alloc,
|
||||
&object_offset,
|
||||
@@ -3169,8 +3427,27 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
return_error_line = __LINE__;
|
||||
goto err_bad_offset;
|
||||
}
|
||||
object_size = binder_get_object(target_proc, t->buffer,
|
||||
object_offset, &object);
|
||||
|
||||
/*
|
||||
* Copy the source user buffer up to the next object
|
||||
* that will be processed.
|
||||
*/
|
||||
copy_size = object_offset - user_offset;
|
||||
if (copy_size && (user_offset > object_offset ||
|
||||
binder_alloc_copy_user_to_buffer(
|
||||
&target_proc->alloc,
|
||||
t->buffer, user_offset,
|
||||
user_buffer + user_offset,
|
||||
copy_size))) {
|
||||
binder_user_error("%d:%d got transaction with invalid data ptr\n",
|
||||
proc->pid, thread->pid);
|
||||
return_error = BR_FAILED_REPLY;
|
||||
return_error_param = -EFAULT;
|
||||
return_error_line = __LINE__;
|
||||
goto err_copy_data_failed;
|
||||
}
|
||||
object_size = binder_get_object(target_proc, user_buffer,
|
||||
t->buffer, object_offset, &object);
|
||||
if (object_size == 0 || object_offset < off_min) {
|
||||
binder_user_error("%d:%d got transaction with invalid offset (%lld, min %lld max %lld) or object.\n",
|
||||
proc->pid, thread->pid,
|
||||
@@ -3182,6 +3459,11 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
return_error_line = __LINE__;
|
||||
goto err_bad_offset;
|
||||
}
|
||||
/*
|
||||
* Set offset to the next buffer fragment to be
|
||||
* copied
|
||||
*/
|
||||
user_offset = object_offset + object_size;
|
||||
|
||||
hdr = &object.hdr;
|
||||
off_min = object_offset + object_size;
|
||||
@@ -3244,6 +3526,8 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
case BINDER_TYPE_FDA: {
|
||||
struct binder_object ptr_object;
|
||||
binder_size_t parent_offset;
|
||||
struct binder_object user_object;
|
||||
size_t user_parent_size;
|
||||
struct binder_fd_array_object *fda =
|
||||
to_binder_fd_array_object(hdr);
|
||||
size_t num_valid = (buffer_offset - off_start_offset) /
|
||||
@@ -3275,11 +3559,35 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
return_error_line = __LINE__;
|
||||
goto err_bad_parent;
|
||||
}
|
||||
ret = binder_translate_fd_array(fda, parent, t, thread,
|
||||
in_reply_to);
|
||||
if (ret < 0) {
|
||||
/*
|
||||
* We need to read the user version of the parent
|
||||
* object to get the original user offset
|
||||
*/
|
||||
user_parent_size =
|
||||
binder_get_object(proc, user_buffer, t->buffer,
|
||||
parent_offset, &user_object);
|
||||
if (user_parent_size != sizeof(user_object.bbo)) {
|
||||
binder_user_error("%d:%d invalid ptr object size: %zd vs %zd\n",
|
||||
proc->pid, thread->pid,
|
||||
user_parent_size,
|
||||
sizeof(user_object.bbo));
|
||||
return_error = BR_FAILED_REPLY;
|
||||
return_error_param = ret;
|
||||
return_error_param = -EINVAL;
|
||||
return_error_line = __LINE__;
|
||||
goto err_bad_parent;
|
||||
}
|
||||
ret = binder_translate_fd_array(&pf_head, fda,
|
||||
user_buffer, parent,
|
||||
&user_object.bbo, t,
|
||||
thread, in_reply_to);
|
||||
if (!ret)
|
||||
ret = binder_alloc_copy_to_buffer(&target_proc->alloc,
|
||||
t->buffer,
|
||||
object_offset,
|
||||
fda, sizeof(*fda));
|
||||
if (ret) {
|
||||
return_error = BR_FAILED_REPLY;
|
||||
return_error_param = ret > 0 ? -EINVAL : ret;
|
||||
return_error_line = __LINE__;
|
||||
goto err_translate_failed;
|
||||
}
|
||||
@@ -3301,19 +3609,14 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
return_error_line = __LINE__;
|
||||
goto err_bad_offset;
|
||||
}
|
||||
if (binder_alloc_copy_user_to_buffer(
|
||||
&target_proc->alloc,
|
||||
t->buffer,
|
||||
sg_buf_offset,
|
||||
(const void __user *)
|
||||
(uintptr_t)bp->buffer,
|
||||
bp->length)) {
|
||||
binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
|
||||
proc->pid, thread->pid);
|
||||
return_error_param = -EFAULT;
|
||||
ret = binder_defer_copy(&sgc_head, sg_buf_offset,
|
||||
(const void __user *)(uintptr_t)bp->buffer,
|
||||
bp->length);
|
||||
if (ret) {
|
||||
return_error = BR_FAILED_REPLY;
|
||||
return_error_param = ret;
|
||||
return_error_line = __LINE__;
|
||||
goto err_copy_data_failed;
|
||||
goto err_translate_failed;
|
||||
}
|
||||
/* Fixup buffer pointer to target proc address space */
|
||||
bp->buffer = (uintptr_t)
|
||||
@@ -3322,7 +3625,8 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
|
||||
num_valid = (buffer_offset - off_start_offset) /
|
||||
sizeof(binder_size_t);
|
||||
ret = binder_fixup_parent(t, thread, bp,
|
||||
ret = binder_fixup_parent(&pf_head, t,
|
||||
thread, bp,
|
||||
off_start_offset,
|
||||
num_valid,
|
||||
last_fixup_obj_off,
|
||||
@@ -3349,6 +3653,30 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
goto err_bad_object_type;
|
||||
}
|
||||
}
|
||||
/* Done processing objects, copy the rest of the buffer */
|
||||
if (binder_alloc_copy_user_to_buffer(
|
||||
&target_proc->alloc,
|
||||
t->buffer, user_offset,
|
||||
user_buffer + user_offset,
|
||||
tr->data_size - user_offset)) {
|
||||
binder_user_error("%d:%d got transaction with invalid data ptr\n",
|
||||
proc->pid, thread->pid);
|
||||
return_error = BR_FAILED_REPLY;
|
||||
return_error_param = -EFAULT;
|
||||
return_error_line = __LINE__;
|
||||
goto err_copy_data_failed;
|
||||
}
|
||||
|
||||
ret = binder_do_deferred_txn_copies(&target_proc->alloc, t->buffer,
|
||||
&sgc_head, &pf_head);
|
||||
if (ret) {
|
||||
binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
|
||||
proc->pid, thread->pid);
|
||||
return_error = BR_FAILED_REPLY;
|
||||
return_error_param = ret;
|
||||
return_error_line = __LINE__;
|
||||
goto err_copy_data_failed;
|
||||
}
|
||||
if (t->buffer->oneway_spam_suspect)
|
||||
tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT;
|
||||
else
|
||||
@@ -3430,6 +3758,7 @@ err_bad_object_type:
|
||||
err_bad_offset:
|
||||
err_bad_parent:
|
||||
err_copy_data_failed:
|
||||
binder_cleanup_deferred_txn_lists(&sgc_head, &pf_head);
|
||||
binder_free_txn_fixups(t);
|
||||
trace_binder_transaction_failed_buffer_release(t->buffer);
|
||||
binder_transaction_buffer_release(target_proc, NULL, t->buffer,
|
||||
|
||||
@@ -213,7 +213,7 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
|
||||
mm = alloc->vma_vm_mm;
|
||||
|
||||
if (mm) {
|
||||
mmap_read_lock(mm);
|
||||
mmap_write_lock(mm);
|
||||
vma = alloc->vma;
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
|
||||
trace_binder_alloc_page_end(alloc, index);
|
||||
}
|
||||
if (mm) {
|
||||
mmap_read_unlock(mm);
|
||||
mmap_write_unlock(mm);
|
||||
mmput(mm);
|
||||
}
|
||||
return 0;
|
||||
@@ -304,7 +304,7 @@ err_page_ptr_cleared:
|
||||
}
|
||||
err_no_vma:
|
||||
if (mm) {
|
||||
mmap_read_unlock(mm);
|
||||
mmap_write_unlock(mm);
|
||||
mmput(mm);
|
||||
}
|
||||
return vma ? -ENOMEM : -ESRCH;
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#include <trace/hooks/iommu.h>
|
||||
#include <trace/hooks/thermal.h>
|
||||
#include <trace/hooks/ufshcd.h>
|
||||
#include <trace/hooks/buffer.h>
|
||||
#ifdef __GENKSYMS__
|
||||
#include <trace/hooks/cgroup.h>
|
||||
#endif
|
||||
@@ -181,7 +182,10 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_irqs_disable);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_irqs_enable);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_set_task_cpu);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_sched_fork);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_wake_up_new_task);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_schedule);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_build_perf_domains);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_update_misfit_status);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_cpu_cgroup_attach);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_cpu_cgroup_can_attach);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_cpu_cgroup_online);
|
||||
@@ -225,6 +229,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_calc_alloc_flags);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_compaction_begin);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_compaction_end);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rmqueue);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_pagevec_drain);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_pagecache_get_page);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_filemap_fault_get_page);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_filemap_fault_cache_page);
|
||||
@@ -253,6 +258,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_create_worker);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_check_preempt_tick);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_check_preempt_wakeup_ignore);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_replace_next_task_fair);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_do_sched_yield);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_wait_for_work);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_sync_txn_recvd);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_build_sched_domains);
|
||||
@@ -281,6 +287,15 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_get_from_fragment_pool);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_exclude_reserved_zone);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_include_reserved_zone);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_pages_slowpath);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_do_madvise_blk_plug);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_shrink_inactive_list_blk_plug);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_shrink_lruvec_blk_plug);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_reclaim_pages_plug);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_zap_pte_range_tlb_start);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_zap_pte_range_tlb_force_flush);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_zap_pte_range_tlb_end);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_bh_lru_install);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_skip_lru_disable);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_cma_alloc_adjust);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_show_mem);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_print_slabinfo_header);
|
||||
|
||||
@@ -2052,9 +2052,9 @@ static int genpd_remove(struct generic_pm_domain *genpd)
|
||||
kfree(link);
|
||||
}
|
||||
|
||||
genpd_debug_remove(genpd);
|
||||
list_del(&genpd->gpd_list_node);
|
||||
genpd_unlock(genpd);
|
||||
genpd_debug_remove(genpd);
|
||||
cancel_work_sync(&genpd->power_off_work);
|
||||
if (genpd_is_cpu_domain(genpd))
|
||||
free_cpumask_var(genpd->cpus);
|
||||
|
||||
@@ -3809,8 +3809,9 @@ struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
|
||||
struct clk *clk_hw_get_clk(struct clk_hw *hw, const char *con_id)
|
||||
{
|
||||
struct device *dev = hw->core->dev;
|
||||
const char *name = dev ? dev_name(dev) : NULL;
|
||||
|
||||
return clk_hw_create_clk(dev, hw, dev_name(dev), con_id);
|
||||
return clk_hw_create_clk(dev, hw, name, con_id);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_hw_get_clk);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
menu "Clock driver for ARM Reference designs"
|
||||
depends on HAS_IOMEM
|
||||
|
||||
config ICST
|
||||
bool "Clock driver for ARM Reference designs ICST"
|
||||
|
||||
@@ -67,7 +67,7 @@ menuconfig DMABUF_HEAPS
|
||||
|
||||
menuconfig DMABUF_SYSFS_STATS
|
||||
bool "DMA-BUF sysfs statistics"
|
||||
select DMA_SHARED_BUFFER
|
||||
depends on DMA_SHARED_BUFFER
|
||||
help
|
||||
Choose this option to enable DMA-BUF sysfs statistics
|
||||
in location /sys/kernel/dmabuf/buffers.
|
||||
|
||||
@@ -126,10 +126,11 @@ static int cma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
|
||||
struct cma_heap_buffer *buffer = dmabuf->priv;
|
||||
struct dma_heap_attachment *a;
|
||||
|
||||
mutex_lock(&buffer->lock);
|
||||
|
||||
if (buffer->vmap_cnt)
|
||||
invalidate_kernel_vmap_range(buffer->vaddr, buffer->len);
|
||||
|
||||
mutex_lock(&buffer->lock);
|
||||
list_for_each_entry(a, &buffer->attachments, list) {
|
||||
if (!a->mapped)
|
||||
continue;
|
||||
@@ -146,10 +147,11 @@ static int cma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
|
||||
struct cma_heap_buffer *buffer = dmabuf->priv;
|
||||
struct dma_heap_attachment *a;
|
||||
|
||||
mutex_lock(&buffer->lock);
|
||||
|
||||
if (buffer->vmap_cnt)
|
||||
flush_kernel_vmap_range(buffer->vaddr, buffer->len);
|
||||
|
||||
mutex_lock(&buffer->lock);
|
||||
list_for_each_entry(a, &buffer->attachments, list) {
|
||||
if (!a->mapped)
|
||||
continue;
|
||||
|
||||
@@ -501,7 +501,7 @@ static int ffa_partition_info_get(const char *uuid_str,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
count = ffa_partition_probe(&uuid_null, &pbuf);
|
||||
count = ffa_partition_probe(&uuid, &pbuf);
|
||||
if (count <= 0)
|
||||
return -ENOENT;
|
||||
|
||||
@@ -607,8 +607,6 @@ static void ffa_setup_partitions(void)
|
||||
__func__, tpbuf->id);
|
||||
continue;
|
||||
}
|
||||
|
||||
ffa_dev_set_drvdata(ffa_dev, drv_info);
|
||||
}
|
||||
kfree(pbuf);
|
||||
}
|
||||
|
||||
@@ -458,7 +458,7 @@ static void mtk_iommu_domain_free(struct iommu_domain *domain)
|
||||
static int mtk_iommu_attach_device(struct iommu_domain *domain,
|
||||
struct device *dev)
|
||||
{
|
||||
struct mtk_iommu_data *data = dev_iommu_priv_get(dev);
|
||||
struct mtk_iommu_data *data = dev_iommu_priv_get(dev), *frstdata;
|
||||
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
|
||||
struct device *m4udev = data->dev;
|
||||
int ret, domid;
|
||||
@@ -468,20 +468,24 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
|
||||
return domid;
|
||||
|
||||
if (!dom->data) {
|
||||
if (mtk_iommu_domain_finalise(dom, data, domid))
|
||||
/* Data is in the frstdata in sharing pgtable case. */
|
||||
frstdata = mtk_iommu_get_m4u_data();
|
||||
|
||||
if (mtk_iommu_domain_finalise(dom, frstdata, domid))
|
||||
return -ENODEV;
|
||||
dom->data = data;
|
||||
}
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
if (!data->m4u_dom) { /* Initialize the M4U HW */
|
||||
ret = pm_runtime_resume_and_get(m4udev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto err_unlock;
|
||||
|
||||
ret = mtk_iommu_hw_init(data);
|
||||
if (ret) {
|
||||
pm_runtime_put(m4udev);
|
||||
return ret;
|
||||
goto err_unlock;
|
||||
}
|
||||
data->m4u_dom = dom;
|
||||
writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
|
||||
@@ -489,9 +493,14 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
|
||||
|
||||
pm_runtime_put(m4udev);
|
||||
}
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
mtk_iommu_config(data, dev, true, domid);
|
||||
return 0;
|
||||
|
||||
err_unlock:
|
||||
mutex_unlock(&data->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mtk_iommu_detach_device(struct iommu_domain *domain,
|
||||
@@ -603,6 +612,7 @@ static struct iommu_group *mtk_iommu_device_group(struct device *dev)
|
||||
if (domid < 0)
|
||||
return ERR_PTR(domid);
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
group = data->m4u_group[domid];
|
||||
if (!group) {
|
||||
group = iommu_group_alloc();
|
||||
@@ -611,6 +621,7 @@ static struct iommu_group *mtk_iommu_device_group(struct device *dev)
|
||||
} else {
|
||||
iommu_group_ref_get(group);
|
||||
}
|
||||
mutex_unlock(&data->mutex);
|
||||
return group;
|
||||
}
|
||||
|
||||
@@ -884,6 +895,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, data);
|
||||
mutex_init(&data->mutex);
|
||||
|
||||
ret = iommu_device_sysfs_add(&data->iommu, dev, NULL,
|
||||
"mtk-iommu.%pa", &ioaddr);
|
||||
@@ -934,7 +946,6 @@ static int mtk_iommu_remove(struct platform_device *pdev)
|
||||
|
||||
list_del(&data->list);
|
||||
|
||||
clk_disable_unprepare(data->bclk);
|
||||
device_link_remove(data->smicomm_dev, &pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
devm_free_irq(&pdev->dev, data->irq, data);
|
||||
|
||||
@@ -80,6 +80,8 @@ struct mtk_iommu_data {
|
||||
|
||||
struct dma_iommu_mapping *mapping; /* For mtk_iommu_v1.c */
|
||||
|
||||
struct mutex mutex; /* Protect m4u_group/m4u_dom above */
|
||||
|
||||
struct list_head list;
|
||||
struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX];
|
||||
};
|
||||
|
||||
@@ -3024,18 +3024,12 @@ static int __init allocate_lpi_tables(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 its_clear_vpend_valid(void __iomem *vlpi_base, u64 clr, u64 set)
|
||||
static u64 read_vpend_dirty_clear(void __iomem *vlpi_base)
|
||||
{
|
||||
u32 count = 1000000; /* 1s! */
|
||||
bool clean;
|
||||
u64 val;
|
||||
|
||||
val = gicr_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
|
||||
val &= ~GICR_VPENDBASER_Valid;
|
||||
val &= ~clr;
|
||||
val |= set;
|
||||
gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
|
||||
|
||||
do {
|
||||
val = gicr_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
|
||||
clean = !(val & GICR_VPENDBASER_Dirty);
|
||||
@@ -3046,10 +3040,26 @@ static u64 its_clear_vpend_valid(void __iomem *vlpi_base, u64 clr, u64 set)
|
||||
}
|
||||
} while (!clean && count);
|
||||
|
||||
if (unlikely(val & GICR_VPENDBASER_Dirty)) {
|
||||
if (unlikely(!clean))
|
||||
pr_err_ratelimited("ITS virtual pending table not cleaning\n");
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static u64 its_clear_vpend_valid(void __iomem *vlpi_base, u64 clr, u64 set)
|
||||
{
|
||||
u64 val;
|
||||
|
||||
/* Make sure we wait until the RD is done with the initial scan */
|
||||
val = read_vpend_dirty_clear(vlpi_base);
|
||||
val &= ~GICR_VPENDBASER_Valid;
|
||||
val &= ~clr;
|
||||
val |= set;
|
||||
gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
|
||||
|
||||
val = read_vpend_dirty_clear(vlpi_base);
|
||||
if (unlikely(val & GICR_VPENDBASER_Dirty))
|
||||
val |= GICR_VPENDBASER_PendingLast;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -188,7 +188,6 @@ static void message_kill(struct message *m, mempool_t *pool)
|
||||
{
|
||||
m->bio->bi_status = BLK_STS_IOERR;
|
||||
bio_endio(m->bio);
|
||||
bio_put(m->bio);
|
||||
mempool_free(m, pool);
|
||||
}
|
||||
|
||||
@@ -989,7 +988,6 @@ finish_bio:
|
||||
*/
|
||||
WARN_ON(bio_size(c->cur_from_user->bio) != 0);
|
||||
bio_endio(c->cur_from_user->bio);
|
||||
bio_put(c->cur_from_user->bio);
|
||||
|
||||
/*
|
||||
* We don't actually need to take the target lock here, as all
|
||||
@@ -1227,7 +1225,6 @@ static int user_map(struct dm_target *ti, struct bio *bio)
|
||||
return DM_MAPIO_REQUEUE;
|
||||
}
|
||||
|
||||
bio_get(bio);
|
||||
entry->msg.type = bio_type_to_user_type(bio);
|
||||
entry->msg.flags = bio_flags_to_user_flags(bio);
|
||||
entry->msg.sector = bio->bi_iter.bi_sector;
|
||||
|
||||
@@ -350,7 +350,7 @@ static int scmi_regulator_probe(struct scmi_device *sdev)
|
||||
if (ret == -ENOMEM)
|
||||
return ret;
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
/*
|
||||
* Register a regulator for each valid regulator-DT-entry that we
|
||||
* can successfully reach via SCMI and has a valid associated voltage
|
||||
|
||||
@@ -97,7 +97,7 @@ MODULE_PARM_DESC(max_luns,
|
||||
#define SCSI_SCAN_TYPE_DEFAULT "sync"
|
||||
#endif
|
||||
|
||||
char scsi_scan_type[7] = SCSI_SCAN_TYPE_DEFAULT;
|
||||
static char scsi_scan_type[7] = SCSI_SCAN_TYPE_DEFAULT;
|
||||
|
||||
module_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type),
|
||||
S_IRUGO|S_IWUSR);
|
||||
@@ -122,7 +122,7 @@ struct async_scan_data {
|
||||
struct completion prev_finished;
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* scsi_enable_async_suspend - Enable async suspend and resume
|
||||
*/
|
||||
void scsi_enable_async_suspend(struct device *dev)
|
||||
|
||||
@@ -816,6 +816,7 @@ out_unlock:
|
||||
static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct ashmem_area *asma = file->private_data;
|
||||
unsigned long ino;
|
||||
long ret = -ENOTTY;
|
||||
|
||||
switch (cmd) {
|
||||
@@ -859,6 +860,23 @@ static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
ashmem_shrink_scan(&ashmem_shrinker, &sc);
|
||||
}
|
||||
break;
|
||||
case ASHMEM_GET_FILE_ID:
|
||||
/* Lock around our check to avoid racing with ashmem_mmap(). */
|
||||
mutex_lock(&ashmem_mutex);
|
||||
if (!asma || !asma->file) {
|
||||
mutex_unlock(&ashmem_mutex);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ino = file_inode(asma->file)->i_ino;
|
||||
mutex_unlock(&ashmem_mutex);
|
||||
|
||||
if (copy_to_user((void __user *)arg, &ino, sizeof(ino))) {
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -41,5 +41,6 @@ struct ashmem_pin {
|
||||
#define ASHMEM_UNPIN _IOW(__ASHMEMIOC, 8, struct ashmem_pin)
|
||||
#define ASHMEM_GET_PIN_STATUS _IO(__ASHMEMIOC, 9)
|
||||
#define ASHMEM_PURGE_ALL_CACHES _IO(__ASHMEMIOC, 10)
|
||||
#define ASHMEM_GET_FILE_ID _IOR(__ASHMEMIOC, 11, unsigned long)
|
||||
|
||||
#endif /* _UAPI_LINUX_ASHMEM_H */
|
||||
|
||||
@@ -3016,6 +3016,48 @@ done:
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* hub_port_stop_enumerate - stop USB enumeration or ignore port events
|
||||
* @hub: target hub
|
||||
* @port1: port num of the port
|
||||
* @retries: port retries number of hub_port_init()
|
||||
*
|
||||
* Return:
|
||||
* true: ignore port actions/events or give up connection attempts.
|
||||
* false: keep original behavior.
|
||||
*
|
||||
* This function will be based on retries to check whether the port which is
|
||||
* marked with early_stop attribute would stop enumeration or ignore events.
|
||||
*
|
||||
* Note:
|
||||
* This function didn't change anything if early_stop is not set, and it will
|
||||
* prevent all connection attempts when early_stop is set and the attempts of
|
||||
* the port are more than 1.
|
||||
*/
|
||||
static bool hub_port_stop_enumerate(struct usb_hub *hub, int port1, int retries)
|
||||
{
|
||||
struct usb_port *port_dev = hub->ports[port1 - 1];
|
||||
|
||||
if (port_dev->early_stop) {
|
||||
if (port_dev->ignore_event)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* We want unsuccessful attempts to fail quickly.
|
||||
* Since some devices may need one failure during
|
||||
* port initialization, we allow two tries but no
|
||||
* more.
|
||||
*/
|
||||
if (retries < 2)
|
||||
return false;
|
||||
|
||||
port_dev->ignore_event = 1;
|
||||
} else
|
||||
port_dev->ignore_event = 0;
|
||||
|
||||
return port_dev->ignore_event;
|
||||
}
|
||||
|
||||
/* Check if a port is power on */
|
||||
static int port_is_power_on(struct usb_hub *hub, unsigned portstatus)
|
||||
{
|
||||
@@ -4729,6 +4771,11 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
|
||||
do_new_scheme = use_new_scheme(udev, retry_counter, port_dev);
|
||||
|
||||
for (retries = 0; retries < GET_DESCRIPTOR_TRIES; (++retries, msleep(100))) {
|
||||
if (hub_port_stop_enumerate(hub, port1, retries)) {
|
||||
retval = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
if (do_new_scheme) {
|
||||
struct usb_device_descriptor *buf;
|
||||
int r = 0;
|
||||
@@ -5173,6 +5220,11 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
|
||||
status = 0;
|
||||
|
||||
for (i = 0; i < PORT_INIT_TRIES; i++) {
|
||||
if (hub_port_stop_enumerate(hub, port1, i)) {
|
||||
status = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
usb_lock_port(port_dev);
|
||||
mutex_lock(hcd->address0_mutex);
|
||||
retry_locked = true;
|
||||
@@ -5542,6 +5594,10 @@ static void port_event(struct usb_hub *hub, int port1)
|
||||
if (!pm_runtime_active(&port_dev->dev))
|
||||
return;
|
||||
|
||||
/* skip port actions if ignore_event and early_stop are true */
|
||||
if (port_dev->ignore_event && port_dev->early_stop)
|
||||
return;
|
||||
|
||||
if (hub_handle_remote_wakeup(hub, port1, portstatus, portchange))
|
||||
connect_change = 1;
|
||||
|
||||
@@ -5854,6 +5910,10 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
|
||||
mutex_lock(hcd->address0_mutex);
|
||||
|
||||
for (i = 0; i < PORT_INIT_TRIES; ++i) {
|
||||
if (hub_port_stop_enumerate(parent_hub, port1, i)) {
|
||||
ret = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
/* ep0 maxpacket size may change; let the HCD know about it.
|
||||
* Other endpoints will be handled by re-enumeration. */
|
||||
|
||||
@@ -89,6 +89,8 @@ struct usb_hub {
|
||||
* @is_superspeed cache super-speed status
|
||||
* @usb3_lpm_u1_permit: whether USB3 U1 LPM is permitted.
|
||||
* @usb3_lpm_u2_permit: whether USB3 U2 LPM is permitted.
|
||||
* @early_stop: whether port initialization will be stopped earlier.
|
||||
* @ignore_event: whether events of the port are ignored.
|
||||
*/
|
||||
struct usb_port {
|
||||
struct usb_device *child;
|
||||
@@ -102,6 +104,8 @@ struct usb_port {
|
||||
u32 over_current_count;
|
||||
u8 portnum;
|
||||
u32 quirks;
|
||||
unsigned int early_stop:1;
|
||||
unsigned int ignore_event:1;
|
||||
unsigned int is_superspeed:1;
|
||||
unsigned int usb3_lpm_u1_permit:1;
|
||||
unsigned int usb3_lpm_u2_permit:1;
|
||||
|
||||
@@ -16,6 +16,32 @@ static int usb_port_block_power_off;
|
||||
|
||||
static const struct attribute_group *port_dev_group[];
|
||||
|
||||
static ssize_t early_stop_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct usb_port *port_dev = to_usb_port(dev);
|
||||
|
||||
return sysfs_emit(buf, "%s\n", port_dev->early_stop ? "yes" : "no");
|
||||
}
|
||||
|
||||
static ssize_t early_stop_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct usb_port *port_dev = to_usb_port(dev);
|
||||
bool value;
|
||||
|
||||
if (kstrtobool(buf, &value))
|
||||
return -EINVAL;
|
||||
|
||||
if (value)
|
||||
port_dev->early_stop = 1;
|
||||
else
|
||||
port_dev->early_stop = 0;
|
||||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(early_stop);
|
||||
|
||||
static ssize_t location_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
@@ -152,6 +178,7 @@ static struct attribute *port_dev_attrs[] = {
|
||||
&dev_attr_location.attr,
|
||||
&dev_attr_quirks.attr,
|
||||
&dev_attr_over_current_count.attr,
|
||||
&dev_attr_early_stop.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
@@ -85,9 +85,25 @@ static int tcpci_write16(struct tcpci *tcpci, unsigned int reg, u16 val)
|
||||
static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
|
||||
{
|
||||
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
|
||||
bool vconn_pres;
|
||||
enum typec_cc_polarity polarity = TYPEC_POLARITY_CC1;
|
||||
unsigned int reg;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(tcpci->regmap, TCPC_POWER_STATUS, ®);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
vconn_pres = !!(reg & TCPC_POWER_STATUS_VCONN_PRES);
|
||||
if (vconn_pres) {
|
||||
ret = regmap_read(tcpci->regmap, TCPC_TCPC_CTRL, ®);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (reg & TCPC_TCPC_CTRL_ORIENTATION)
|
||||
polarity = TYPEC_POLARITY_CC2;
|
||||
}
|
||||
|
||||
switch (cc) {
|
||||
case TYPEC_CC_RA:
|
||||
reg = (TCPC_ROLE_CTRL_CC_RA << TCPC_ROLE_CTRL_CC1_SHIFT) |
|
||||
@@ -122,6 +138,16 @@ static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
|
||||
break;
|
||||
}
|
||||
|
||||
if (vconn_pres) {
|
||||
if (polarity == TYPEC_POLARITY_CC2) {
|
||||
reg &= ~(TCPC_ROLE_CTRL_CC1_MASK << TCPC_ROLE_CTRL_CC1_SHIFT);
|
||||
reg |= (TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC1_SHIFT);
|
||||
} else {
|
||||
reg &= ~(TCPC_ROLE_CTRL_CC2_MASK << TCPC_ROLE_CTRL_CC2_SHIFT);
|
||||
reg |= (TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC2_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
ret = regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
#define TCPC_POWER_STATUS_SOURCING_VBUS BIT(4)
|
||||
#define TCPC_POWER_STATUS_VBUS_DET BIT(3)
|
||||
#define TCPC_POWER_STATUS_VBUS_PRES BIT(2)
|
||||
#define TCPC_POWER_STATUS_VCONN_PRES BIT(1)
|
||||
#define TCPC_POWER_STATUS_SINKING_VBUS BIT(0)
|
||||
|
||||
#define TCPC_FAULT_STATUS 0x1f
|
||||
|
||||
@@ -5384,6 +5384,10 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port)
|
||||
case PR_SWAP_SNK_SRC_SOURCE_ON:
|
||||
/* Do nothing, vsafe0v is expected during transition */
|
||||
break;
|
||||
case SNK_ATTACH_WAIT:
|
||||
case SNK_DEBOUNCED:
|
||||
/*Do nothing, still waiting for VSAFE5V for connect */
|
||||
break;
|
||||
default:
|
||||
if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled)
|
||||
tcpm_set_state(port, SNK_UNATTACHED, 0);
|
||||
|
||||
@@ -452,8 +452,9 @@ int virtio_device_restore(struct virtio_device *dev)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Finally, tell the device we're all set */
|
||||
virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
|
||||
/* If restore didn't do it, mark device DRIVER_OK ourselves. */
|
||||
if (!(dev->config->get_status(dev) & VIRTIO_CONFIG_S_DRIVER_OK))
|
||||
virtio_device_ready(dev);
|
||||
|
||||
virtio_config_enable(dev);
|
||||
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <trace/hooks/buffer.h>
|
||||
|
||||
static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
|
||||
static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh,
|
||||
enum rw_hint hint, struct writeback_control *wbc);
|
||||
@@ -1262,6 +1264,7 @@ static void bh_lru_install(struct buffer_head *bh)
|
||||
struct buffer_head *evictee = bh;
|
||||
struct bh_lru *b;
|
||||
int i;
|
||||
bool skip = false;
|
||||
|
||||
check_irqs_on();
|
||||
/*
|
||||
@@ -1273,6 +1276,10 @@ static void bh_lru_install(struct buffer_head *bh)
|
||||
if (lru_cache_disabled())
|
||||
return;
|
||||
|
||||
trace_android_vh_bh_lru_install(bh->b_page, &skip);
|
||||
if (skip)
|
||||
return;
|
||||
|
||||
bh_lru_lock();
|
||||
|
||||
b = this_cpu_ptr(&bh_lrus);
|
||||
|
||||
@@ -204,9 +204,11 @@ void erofs_unregister_sysfs(struct super_block *sb)
|
||||
{
|
||||
struct erofs_sb_info *sbi = EROFS_SB(sb);
|
||||
|
||||
kobject_del(&sbi->s_kobj);
|
||||
kobject_put(&sbi->s_kobj);
|
||||
wait_for_completion(&sbi->s_kobj_unregister);
|
||||
if (sbi->s_kobj.state_in_sysfs) {
|
||||
kobject_del(&sbi->s_kobj);
|
||||
kobject_put(&sbi->s_kobj);
|
||||
wait_for_completion(&sbi->s_kobj_unregister);
|
||||
}
|
||||
}
|
||||
|
||||
int __init erofs_init_sysfs(void)
|
||||
|
||||
@@ -1029,10 +1029,10 @@ static int exec_mmap(struct mm_struct *mm)
|
||||
activate_mm(active_mm, mm);
|
||||
if (IS_ENABLED(CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM))
|
||||
local_irq_enable();
|
||||
lru_gen_use_mm(mm);
|
||||
tsk->mm->vmacache_seqnum = 0;
|
||||
vmacache_flush(tsk);
|
||||
task_unlock(tsk);
|
||||
lru_gen_use_mm(mm);
|
||||
if (old_mm) {
|
||||
mmap_read_unlock(old_mm);
|
||||
BUG_ON(active_mm != old_mm);
|
||||
|
||||
@@ -370,13 +370,14 @@ static struct page *ext4_read_merkle_tree_page(struct inode *inode,
|
||||
pgoff_t index,
|
||||
unsigned long num_ra_pages)
|
||||
{
|
||||
DEFINE_READAHEAD(ractl, NULL, inode->i_mapping, index);
|
||||
struct page *page;
|
||||
|
||||
index += ext4_verity_metadata_pos(inode) >> PAGE_SHIFT;
|
||||
|
||||
page = find_get_page_flags(inode->i_mapping, index, FGP_ACCESSED);
|
||||
if (!page || !PageUptodate(page)) {
|
||||
DEFINE_READAHEAD(ractl, NULL, inode->i_mapping, index);
|
||||
|
||||
if (page)
|
||||
put_page(page);
|
||||
else if (num_ra_pages > 1)
|
||||
|
||||
@@ -26,12 +26,16 @@
|
||||
static struct kmem_cache *ino_entry_slab;
|
||||
struct kmem_cache *f2fs_inode_entry_slab;
|
||||
|
||||
void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io)
|
||||
void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io,
|
||||
unsigned char reason)
|
||||
{
|
||||
f2fs_build_fault_attr(sbi, 0, 0);
|
||||
set_ckpt_flags(sbi, CP_ERROR_FLAG);
|
||||
if (!end_io)
|
||||
if (!end_io) {
|
||||
f2fs_flush_merged_writes(sbi);
|
||||
|
||||
f2fs_handle_stop(sbi, reason);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -122,7 +126,7 @@ retry:
|
||||
if (PTR_ERR(page) == -EIO &&
|
||||
++count <= DEFAULT_RETRY_IO_COUNT)
|
||||
goto retry;
|
||||
f2fs_stop_checkpoint(sbi, false);
|
||||
f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_META_PAGE);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
@@ -336,7 +336,8 @@ static void f2fs_write_end_io(struct bio *bio)
|
||||
mempool_free(page, sbi->write_io_dummy);
|
||||
|
||||
if (unlikely(bio->bi_status))
|
||||
f2fs_stop_checkpoint(sbi, true);
|
||||
f2fs_stop_checkpoint(sbi, true,
|
||||
STOP_CP_REASON_WRITE_FAIL);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -352,7 +353,8 @@ static void f2fs_write_end_io(struct bio *bio)
|
||||
if (unlikely(bio->bi_status)) {
|
||||
mapping_set_error(page->mapping, -EIO);
|
||||
if (type == F2FS_WB_CP_DATA)
|
||||
f2fs_stop_checkpoint(sbi, true);
|
||||
f2fs_stop_checkpoint(sbi, true,
|
||||
STOP_CP_REASON_WRITE_FAIL);
|
||||
}
|
||||
|
||||
f2fs_bug_on(sbi, page->mapping == NODE_MAPPING(sbi) &&
|
||||
|
||||
@@ -82,7 +82,8 @@ int f2fs_init_casefolded_name(const struct inode *dir,
|
||||
#ifdef CONFIG_UNICODE
|
||||
struct super_block *sb = dir->i_sb;
|
||||
|
||||
if (IS_CASEFOLDED(dir)) {
|
||||
if (IS_CASEFOLDED(dir) &&
|
||||
!is_dot_dotdot(fname->usr_fname->name, fname->usr_fname->len)) {
|
||||
fname->cf_name.name = f2fs_kmem_cache_alloc(f2fs_cf_name_slab,
|
||||
GFP_NOFS, false, F2FS_SB(sb));
|
||||
if (!fname->cf_name.name)
|
||||
|
||||
@@ -512,11 +512,11 @@ struct f2fs_filename {
|
||||
#ifdef CONFIG_UNICODE
|
||||
/*
|
||||
* For casefolded directories: the casefolded name, but it's left NULL
|
||||
* if the original name is not valid Unicode, if the directory is both
|
||||
* casefolded and encrypted and its encryption key is unavailable, or if
|
||||
* the filesystem is doing an internal operation where usr_fname is also
|
||||
* NULL. In all these cases we fall back to treating the name as an
|
||||
* opaque byte sequence.
|
||||
* if the original name is not valid Unicode, if the original name is
|
||||
* "." or "..", if the directory is both casefolded and encrypted and
|
||||
* its encryption key is unavailable, or if the filesystem is doing an
|
||||
* internal operation where usr_fname is also NULL. In all these cases
|
||||
* we fall back to treating the name as an opaque byte sequence.
|
||||
*/
|
||||
struct fscrypt_str cf_name;
|
||||
#endif
|
||||
@@ -3527,6 +3527,7 @@ int f2fs_enable_quota_files(struct f2fs_sb_info *sbi, bool rdonly);
|
||||
int f2fs_quota_sync(struct super_block *sb, int type);
|
||||
loff_t max_file_blocks(struct inode *inode);
|
||||
void f2fs_quota_off_umount(struct super_block *sb);
|
||||
void f2fs_handle_stop(struct f2fs_sb_info *sbi, unsigned char reason);
|
||||
int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover);
|
||||
int f2fs_sync_fs(struct super_block *sb, int sync);
|
||||
int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi);
|
||||
@@ -3691,7 +3692,8 @@ static inline bool f2fs_need_rand_seg(struct f2fs_sb_info *sbi)
|
||||
/*
|
||||
* checkpoint.c
|
||||
*/
|
||||
void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io);
|
||||
void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io,
|
||||
unsigned char reason);
|
||||
void f2fs_flush_ckpt_thread(struct f2fs_sb_info *sbi);
|
||||
struct page *f2fs_grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index);
|
||||
struct page *f2fs_get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index);
|
||||
|
||||
@@ -2278,7 +2278,8 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
|
||||
if (ret) {
|
||||
if (ret == -EROFS) {
|
||||
ret = 0;
|
||||
f2fs_stop_checkpoint(sbi, false);
|
||||
f2fs_stop_checkpoint(sbi, false,
|
||||
STOP_CP_REASON_SHUTDOWN);
|
||||
set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
|
||||
trace_f2fs_shutdown(sbi, in, ret);
|
||||
}
|
||||
@@ -2291,7 +2292,7 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
|
||||
ret = freeze_bdev(sb->s_bdev);
|
||||
if (ret)
|
||||
goto out;
|
||||
f2fs_stop_checkpoint(sbi, false);
|
||||
f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
|
||||
set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
|
||||
thaw_bdev(sb->s_bdev);
|
||||
break;
|
||||
@@ -2300,16 +2301,16 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
|
||||
ret = f2fs_sync_fs(sb, 1);
|
||||
if (ret)
|
||||
goto out;
|
||||
f2fs_stop_checkpoint(sbi, false);
|
||||
f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
|
||||
set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
|
||||
break;
|
||||
case F2FS_GOING_DOWN_NOSYNC:
|
||||
f2fs_stop_checkpoint(sbi, false);
|
||||
f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
|
||||
set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
|
||||
break;
|
||||
case F2FS_GOING_DOWN_METAFLUSH:
|
||||
f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_META_IO);
|
||||
f2fs_stop_checkpoint(sbi, false);
|
||||
f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
|
||||
set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
|
||||
break;
|
||||
case F2FS_GOING_DOWN_NEED_FSCK:
|
||||
|
||||
@@ -70,7 +70,8 @@ static int gc_thread_func(void *data)
|
||||
|
||||
if (time_to_inject(sbi, FAULT_CHECKPOINT)) {
|
||||
f2fs_show_injection_info(sbi, FAULT_CHECKPOINT);
|
||||
f2fs_stop_checkpoint(sbi, false);
|
||||
f2fs_stop_checkpoint(sbi, false,
|
||||
STOP_CP_REASON_FAULT_INJECT);
|
||||
}
|
||||
|
||||
if (!sb_start_write_trylock(sbi->sb)) {
|
||||
@@ -1660,7 +1661,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
|
||||
f2fs_err(sbi, "Inconsistent segment (%u) type [%d, %d] in SSA and SIT",
|
||||
segno, type, GET_SUM_TYPE((&sum->footer)));
|
||||
set_sbi_flag(sbi, SBI_NEED_FSCK);
|
||||
f2fs_stop_checkpoint(sbi, false);
|
||||
f2fs_stop_checkpoint(sbi, false,
|
||||
STOP_CP_REASON_CORRUPTED_SUMMARY);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ static u32 TEA_hash_name(const u8 *p, size_t len)
|
||||
/*
|
||||
* Compute @fname->hash. For all directories, @fname->disk_name must be set.
|
||||
* For casefolded directories, @fname->usr_fname must be set, and also
|
||||
* @fname->cf_name if the filename is valid Unicode.
|
||||
* @fname->cf_name if the filename is valid Unicode and is not "." or "..".
|
||||
*/
|
||||
void f2fs_hash_filename(const struct inode *dir, struct f2fs_filename *fname)
|
||||
{
|
||||
@@ -110,10 +110,11 @@ void f2fs_hash_filename(const struct inode *dir, struct f2fs_filename *fname)
|
||||
/*
|
||||
* If the casefolded name is provided, hash it instead of the
|
||||
* on-disk name. If the casefolded name is *not* provided, that
|
||||
* should only be because the name wasn't valid Unicode, so fall
|
||||
* back to treating the name as an opaque byte sequence. Note
|
||||
* that to handle encrypted directories, the fallback must use
|
||||
* usr_fname (plaintext) rather than disk_name (ciphertext).
|
||||
* should only be because the name wasn't valid Unicode or was
|
||||
* "." or "..", so fall back to treating the name as an opaque
|
||||
* byte sequence. Note that to handle encrypted directories,
|
||||
* the fallback must use usr_fname (plaintext) rather than
|
||||
* disk_name (ciphertext).
|
||||
*/
|
||||
WARN_ON_ONCE(!fname->usr_fname->name);
|
||||
if (fname->cf_name.name) {
|
||||
|
||||
@@ -699,7 +699,8 @@ retry:
|
||||
cond_resched();
|
||||
goto retry;
|
||||
} else if (err != -ENOENT) {
|
||||
f2fs_stop_checkpoint(sbi, false);
|
||||
f2fs_stop_checkpoint(sbi, false,
|
||||
STOP_CP_REASON_UPDATE_INODE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -628,6 +628,8 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
goto fail;
|
||||
}
|
||||
f2fs_delete_entry(de, page, dir, inode);
|
||||
f2fs_unlock_op(sbi);
|
||||
|
||||
#ifdef CONFIG_UNICODE
|
||||
/* VFS negative dentries are incompatible with Encoding and
|
||||
* Case-insensitiveness. Eventually we'll want avoid
|
||||
@@ -638,8 +640,6 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
if (IS_CASEFOLDED(dir))
|
||||
d_invalidate(dentry);
|
||||
#endif
|
||||
f2fs_unlock_op(sbi);
|
||||
|
||||
if (IS_DIRSYNC(dir))
|
||||
f2fs_sync_fs(sbi->sb, 1);
|
||||
fail:
|
||||
|
||||
@@ -1362,8 +1362,7 @@ static int read_node_page(struct page *page, int op_flags)
|
||||
return err;
|
||||
|
||||
/* NEW_ADDR can be seen, after cp_error drops some dirty node pages */
|
||||
if (unlikely(ni.blk_addr == NULL_ADDR || ni.blk_addr == NEW_ADDR) ||
|
||||
is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN)) {
|
||||
if (unlikely(ni.blk_addr == NULL_ADDR || ni.blk_addr == NEW_ADDR)) {
|
||||
ClearPageUptodate(page);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@@ -501,7 +501,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
|
||||
{
|
||||
if (time_to_inject(sbi, FAULT_CHECKPOINT)) {
|
||||
f2fs_show_injection_info(sbi, FAULT_CHECKPOINT);
|
||||
f2fs_stop_checkpoint(sbi, false);
|
||||
f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_FAULT_INJECT);
|
||||
}
|
||||
|
||||
/* balance_fs_bg is able to be pending */
|
||||
@@ -812,7 +812,8 @@ int f2fs_flush_device_cache(struct f2fs_sb_info *sbi)
|
||||
} while (ret && --count);
|
||||
|
||||
if (ret) {
|
||||
f2fs_stop_checkpoint(sbi, false);
|
||||
f2fs_stop_checkpoint(sbi, false,
|
||||
STOP_CP_REASON_FLUSH_FAIL);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -3863,6 +3863,26 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover)
|
||||
return err;
|
||||
}
|
||||
|
||||
void f2fs_handle_stop(struct f2fs_sb_info *sbi, unsigned char reason)
|
||||
{
|
||||
struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
|
||||
int err;
|
||||
|
||||
f2fs_bug_on(sbi, reason >= MAX_STOP_REASON);
|
||||
|
||||
f2fs_down_write(&sbi->sb_lock);
|
||||
|
||||
if (raw_super->s_stop_reason[reason] < ((1 << BITS_PER_BYTE) - 1))
|
||||
raw_super->s_stop_reason[reason]++;
|
||||
|
||||
err = f2fs_commit_super(sbi, false);
|
||||
if (err)
|
||||
f2fs_err(sbi, "f2fs_commit_super fails to record reason:%u err:%d",
|
||||
reason, err);
|
||||
|
||||
f2fs_up_write(&sbi->sb_lock);
|
||||
}
|
||||
|
||||
static int f2fs_scan_devices(struct f2fs_sb_info *sbi)
|
||||
{
|
||||
struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
|
||||
|
||||
@@ -261,13 +261,14 @@ static struct page *f2fs_read_merkle_tree_page(struct inode *inode,
|
||||
pgoff_t index,
|
||||
unsigned long num_ra_pages)
|
||||
{
|
||||
DEFINE_READAHEAD(ractl, NULL, inode->i_mapping, index);
|
||||
struct page *page;
|
||||
|
||||
index += f2fs_verity_metadata_pos(inode) >> PAGE_SHIFT;
|
||||
|
||||
page = find_get_page_flags(inode->i_mapping, index, FGP_ACCESSED);
|
||||
if (!page || !PageUptodate(page)) {
|
||||
DEFINE_READAHEAD(ractl, NULL, inode->i_mapping, index);
|
||||
|
||||
if (page)
|
||||
put_page(page);
|
||||
else if (num_ra_pages > 1)
|
||||
|
||||
23
fs/proc/fd.c
23
fs/proc/fd.c
@@ -71,7 +71,7 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int seq_fdinfo_open(struct inode *inode, struct file *file)
|
||||
static int proc_fdinfo_access_allowed(struct inode *inode)
|
||||
{
|
||||
bool allowed = false;
|
||||
struct task_struct *task = get_proc_task(inode);
|
||||
@@ -85,6 +85,16 @@ static int seq_fdinfo_open(struct inode *inode, struct file *file)
|
||||
if (!allowed)
|
||||
return -EACCES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int seq_fdinfo_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int ret = proc_fdinfo_access_allowed(inode);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return single_open(file, seq_show, inode);
|
||||
}
|
||||
|
||||
@@ -365,12 +375,23 @@ static int proc_readfdinfo(struct file *file, struct dir_context *ctx)
|
||||
proc_fdinfo_instantiate);
|
||||
}
|
||||
|
||||
static int proc_open_fdinfo(struct inode *inode, struct file *file)
|
||||
{
|
||||
int ret = proc_fdinfo_access_allowed(inode);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct inode_operations proc_fdinfo_inode_operations = {
|
||||
.lookup = proc_lookupfdinfo,
|
||||
.setattr = proc_setattr,
|
||||
};
|
||||
|
||||
const struct file_operations proc_fdinfo_operations = {
|
||||
.open = proc_open_fdinfo,
|
||||
.read = generic_read_dir,
|
||||
.iterate_shared = proc_readfdinfo,
|
||||
.llseek = generic_file_llseek,
|
||||
|
||||
@@ -73,6 +73,20 @@ struct f2fs_device {
|
||||
__le32 total_segments;
|
||||
} __packed;
|
||||
|
||||
/* reason of stop_checkpoint */
|
||||
enum stop_cp_reason {
|
||||
STOP_CP_REASON_SHUTDOWN,
|
||||
STOP_CP_REASON_FAULT_INJECT,
|
||||
STOP_CP_REASON_META_PAGE,
|
||||
STOP_CP_REASON_WRITE_FAIL,
|
||||
STOP_CP_REASON_CORRUPTED_SUMMARY,
|
||||
STOP_CP_REASON_UPDATE_INODE,
|
||||
STOP_CP_REASON_FLUSH_FAIL,
|
||||
STOP_CP_REASON_MAX,
|
||||
};
|
||||
|
||||
#define MAX_STOP_REASON 32
|
||||
|
||||
struct f2fs_super_block {
|
||||
__le32 magic; /* Magic Number */
|
||||
__le16 major_ver; /* Major Version */
|
||||
@@ -116,7 +130,8 @@ struct f2fs_super_block {
|
||||
__u8 hot_ext_count; /* # of hot file extension */
|
||||
__le16 s_encoding; /* Filename charset encoding */
|
||||
__le16 s_encoding_flags; /* Filename charset encoding flags */
|
||||
__u8 reserved[306]; /* valid reserved region */
|
||||
__u8 s_stop_reason[MAX_STOP_REASON]; /* stop checkpoint reason */
|
||||
__u8 reserved[274]; /* valid reserved region */
|
||||
__le32 crc; /* checksum of superblock */
|
||||
} __packed;
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/atomic.h>
|
||||
#if defined(CONFIG_ARM64) && !defined(__GENKSYMS__)
|
||||
#include <linux/mmu_context.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FREEZER
|
||||
extern atomic_t system_freezing_cnt; /* nr of freezing conds in effect */
|
||||
@@ -108,10 +111,15 @@ static inline bool cgroup_freezing(struct task_struct *task)
|
||||
* The caller shouldn't do anything which isn't allowed for a frozen task
|
||||
* until freezer_cont() is called. Usually, freezer[_do_not]_count() pair
|
||||
* wrap a scheduling operation and nothing much else.
|
||||
*
|
||||
* The write to current->flags uses release semantics to prevent a concurrent
|
||||
* freezer_should_skip() from observing this write before a write to on_rq
|
||||
* during a prior call to activate_task(), which may cause it to return true
|
||||
* before deactivate_task() is called.
|
||||
*/
|
||||
static inline void freezer_do_not_count(void)
|
||||
{
|
||||
current->flags |= PF_FREEZER_SKIP;
|
||||
smp_store_release(¤t->flags, current->flags | PF_FREEZER_SKIP);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,7 +169,19 @@ static inline bool freezer_should_skip(struct task_struct *p)
|
||||
* clearing %PF_FREEZER_SKIP.
|
||||
*/
|
||||
smp_mb();
|
||||
#ifdef CONFIG_ARM64
|
||||
return (p->flags & PF_FREEZER_SKIP) &&
|
||||
(!p->on_rq || task_cpu_possible_mask(p) == cpu_possible_mask);
|
||||
#else
|
||||
/*
|
||||
* On non-aarch64, avoid depending on task_cpu_possible_mask(), which is
|
||||
* defined in <linux/mmu_context.h>, because including that header from
|
||||
* here exposes a tricky bug in the tracepoint headers on x86, and that
|
||||
* macro would end up being defined equal to cpu_possible_mask on other
|
||||
* architectures anyway.
|
||||
*/
|
||||
return p->flags & PF_FREEZER_SKIP;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1761,6 +1761,12 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
|
||||
#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
|
||||
static inline void vm_write_begin(struct vm_area_struct *vma)
|
||||
{
|
||||
/*
|
||||
* Isolated vma might be freed without exclusive mmap_lock but
|
||||
* speculative page fault handler still needs to know it was changed.
|
||||
*/
|
||||
if (!RB_EMPTY_NODE(&vma->vm_rb))
|
||||
mmap_assert_write_locked(vma->vm_mm);
|
||||
/*
|
||||
* The reads never spins and preemption
|
||||
* disablement is not required.
|
||||
|
||||
@@ -27,11 +27,12 @@ static inline int page_is_file_lru(struct page *page)
|
||||
|
||||
static __always_inline void __update_lru_size(struct lruvec *lruvec,
|
||||
enum lru_list lru, enum zone_type zid,
|
||||
int nr_pages)
|
||||
long nr_pages)
|
||||
{
|
||||
struct pglist_data *pgdat = lruvec_pgdat(lruvec);
|
||||
|
||||
lockdep_assert_held(&pgdat->lru_lock);
|
||||
WARN_ON_ONCE(nr_pages != (int)nr_pages);
|
||||
|
||||
__mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages);
|
||||
__mod_zone_page_state(&pgdat->node_zones[zid],
|
||||
@@ -91,18 +92,21 @@ static __always_inline enum lru_list page_lru(struct page *page)
|
||||
|
||||
#ifdef CONFIG_LRU_GEN
|
||||
|
||||
#ifdef CONFIG_LRU_GEN_ENABLED
|
||||
static inline bool lru_gen_enabled(void)
|
||||
{
|
||||
#ifdef CONFIG_LRU_GEN_ENABLED
|
||||
DECLARE_STATIC_KEY_TRUE(lru_gen_caps[NR_LRU_GEN_CAPS]);
|
||||
|
||||
return static_branch_likely(&lru_gen_caps[LRU_GEN_CORE]);
|
||||
}
|
||||
#else
|
||||
static inline bool lru_gen_enabled(void)
|
||||
{
|
||||
DECLARE_STATIC_KEY_FALSE(lru_gen_caps[NR_LRU_GEN_CAPS]);
|
||||
|
||||
return static_branch_unlikely(&lru_gen_caps[LRU_GEN_CORE]);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline bool lru_gen_in_fault(void)
|
||||
{
|
||||
@@ -121,17 +125,38 @@ static inline int lru_hist_from_seq(unsigned long seq)
|
||||
|
||||
static inline int lru_tier_from_refs(int refs)
|
||||
{
|
||||
VM_BUG_ON(refs > BIT(LRU_REFS_WIDTH));
|
||||
VM_WARN_ON_ONCE(refs > BIT(LRU_REFS_WIDTH));
|
||||
|
||||
/* see the comment on MAX_NR_TIERS */
|
||||
/* see the comment in page_lru_refs() */
|
||||
return order_base_2(refs + 1);
|
||||
}
|
||||
|
||||
static inline int page_lru_refs(struct page *page)
|
||||
{
|
||||
unsigned long flags = READ_ONCE(page->flags);
|
||||
bool workingset = flags & BIT(PG_workingset);
|
||||
|
||||
/*
|
||||
* Return the number of accesses beyond PG_referenced, i.e., N-1 if the
|
||||
* total number of accesses is N>1, since N=0,1 both map to the first
|
||||
* tier. lru_tier_from_refs() will account for this off-by-one. Also see
|
||||
* the comment on MAX_NR_TIERS.
|
||||
*/
|
||||
return ((flags & LRU_REFS_MASK) >> LRU_REFS_PGOFF) + workingset;
|
||||
}
|
||||
|
||||
static inline int page_lru_gen(struct page *page)
|
||||
{
|
||||
unsigned long flags = READ_ONCE(page->flags);
|
||||
|
||||
return ((flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1;
|
||||
}
|
||||
|
||||
static inline bool lru_gen_is_active(struct lruvec *lruvec, int gen)
|
||||
{
|
||||
unsigned long max_seq = lruvec->lrugen.max_seq;
|
||||
|
||||
VM_BUG_ON(gen >= MAX_NR_GENS);
|
||||
VM_WARN_ON_ONCE(gen >= MAX_NR_GENS);
|
||||
|
||||
/* see the comment on MIN_NR_GENS */
|
||||
return gen == lru_gen_from_seq(max_seq) || gen == lru_gen_from_seq(max_seq - 1);
|
||||
@@ -146,9 +171,9 @@ static inline void lru_gen_update_size(struct lruvec *lruvec, struct page *page,
|
||||
enum lru_list lru = type * LRU_INACTIVE_FILE;
|
||||
struct lru_gen_struct *lrugen = &lruvec->lrugen;
|
||||
|
||||
VM_BUG_ON(old_gen != -1 && old_gen >= MAX_NR_GENS);
|
||||
VM_BUG_ON(new_gen != -1 && new_gen >= MAX_NR_GENS);
|
||||
VM_BUG_ON(old_gen == -1 && new_gen == -1);
|
||||
VM_WARN_ON_ONCE(old_gen != -1 && old_gen >= MAX_NR_GENS);
|
||||
VM_WARN_ON_ONCE(new_gen != -1 && new_gen >= MAX_NR_GENS);
|
||||
VM_WARN_ON_ONCE(old_gen == -1 && new_gen == -1);
|
||||
|
||||
if (old_gen >= 0)
|
||||
WRITE_ONCE(lrugen->nr_pages[old_gen][type][zone],
|
||||
@@ -180,17 +205,20 @@ static inline void lru_gen_update_size(struct lruvec *lruvec, struct page *page,
|
||||
}
|
||||
|
||||
/* demotion requires isolation, e.g., lru_deactivate_fn() */
|
||||
VM_BUG_ON(lru_gen_is_active(lruvec, old_gen) && !lru_gen_is_active(lruvec, new_gen));
|
||||
VM_WARN_ON_ONCE(lru_gen_is_active(lruvec, old_gen) && !lru_gen_is_active(lruvec, new_gen));
|
||||
}
|
||||
|
||||
static inline bool lru_gen_add_page(struct lruvec *lruvec, struct page *page, bool reclaiming)
|
||||
{
|
||||
int gen;
|
||||
unsigned long old_flags, new_flags;
|
||||
unsigned long seq;
|
||||
unsigned long flags;
|
||||
int gen = page_lru_gen(page);
|
||||
int type = page_is_file_lru(page);
|
||||
int zone = page_zonenum(page);
|
||||
struct lru_gen_struct *lrugen = &lruvec->lrugen;
|
||||
|
||||
VM_WARN_ON_ONCE_PAGE(gen != -1, page);
|
||||
|
||||
if (PageUnevictable(page) || !lrugen->enabled)
|
||||
return false;
|
||||
/*
|
||||
@@ -203,21 +231,18 @@ static inline bool lru_gen_add_page(struct lruvec *lruvec, struct page *page, bo
|
||||
* 3. Everything else (clean, cold) is added to the oldest generation.
|
||||
*/
|
||||
if (PageActive(page))
|
||||
gen = lru_gen_from_seq(lrugen->max_seq);
|
||||
seq = lrugen->max_seq;
|
||||
else if ((type == LRU_GEN_ANON && !PageSwapCache(page)) ||
|
||||
(PageReclaim(page) && (PageDirty(page) || PageWriteback(page))))
|
||||
gen = lru_gen_from_seq(lrugen->min_seq[type] + 1);
|
||||
(PageReclaim(page) &&
|
||||
(PageDirty(page) || PageWriteback(page))))
|
||||
seq = lrugen->min_seq[type] + 1;
|
||||
else
|
||||
gen = lru_gen_from_seq(lrugen->min_seq[type]);
|
||||
seq = lrugen->min_seq[type];
|
||||
|
||||
do {
|
||||
new_flags = old_flags = READ_ONCE(page->flags);
|
||||
VM_BUG_ON_PAGE(new_flags & LRU_GEN_MASK, page);
|
||||
|
||||
/* see the comment on MIN_NR_GENS */
|
||||
new_flags &= ~(LRU_GEN_MASK | BIT(PG_active));
|
||||
new_flags |= (gen + 1UL) << LRU_GEN_PGOFF;
|
||||
} while (cmpxchg(&page->flags, old_flags, new_flags) != old_flags);
|
||||
gen = lru_gen_from_seq(seq);
|
||||
flags = (gen + 1UL) << LRU_GEN_PGOFF;
|
||||
/* see the comment on MIN_NR_GENS about PG_active */
|
||||
set_mask_bits(&page->flags, LRU_GEN_MASK | BIT(PG_active), flags);
|
||||
|
||||
lru_gen_update_size(lruvec, page, -1, gen);
|
||||
/* for rotate_reclaimable_page() */
|
||||
@@ -231,28 +256,19 @@ static inline bool lru_gen_add_page(struct lruvec *lruvec, struct page *page, bo
|
||||
|
||||
static inline bool lru_gen_del_page(struct lruvec *lruvec, struct page *page, bool reclaiming)
|
||||
{
|
||||
int gen;
|
||||
unsigned long old_flags, new_flags;
|
||||
unsigned long flags;
|
||||
int gen = page_lru_gen(page);
|
||||
|
||||
do {
|
||||
new_flags = old_flags = READ_ONCE(page->flags);
|
||||
if (!(new_flags & LRU_GEN_MASK))
|
||||
return false;
|
||||
if (gen < 0)
|
||||
return false;
|
||||
|
||||
VM_BUG_ON_PAGE(PageActive(page), page);
|
||||
VM_BUG_ON_PAGE(PageUnevictable(page), page);
|
||||
VM_WARN_ON_ONCE_PAGE(PageActive(page), page);
|
||||
VM_WARN_ON_ONCE_PAGE(PageUnevictable(page), page);
|
||||
|
||||
gen = ((new_flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1;
|
||||
|
||||
new_flags &= ~LRU_GEN_MASK;
|
||||
if (!(new_flags & BIT(PG_referenced)))
|
||||
new_flags &= ~(LRU_REFS_MASK | LRU_REFS_FLAGS);
|
||||
/* for shrink_page_list() */
|
||||
if (reclaiming)
|
||||
new_flags &= ~(BIT(PG_referenced) | BIT(PG_reclaim));
|
||||
else if (lru_gen_is_active(lruvec, gen))
|
||||
new_flags |= BIT(PG_active);
|
||||
} while (cmpxchg(&page->flags, old_flags, new_flags) != old_flags);
|
||||
/* for migrate_page_states() */
|
||||
flags = !reclaiming && lru_gen_is_active(lruvec, gen) ? BIT(PG_active) : 0;
|
||||
flags = set_mask_bits(&page->flags, LRU_GEN_MASK, flags);
|
||||
gen = ((flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1;
|
||||
|
||||
lru_gen_update_size(lruvec, page, gen, -1);
|
||||
list_del(&page->lru);
|
||||
@@ -260,7 +276,7 @@ static inline bool lru_gen_del_page(struct lruvec *lruvec, struct page *page, bo
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
#else /* !CONFIG_LRU_GEN */
|
||||
|
||||
static inline bool lru_gen_enabled(void)
|
||||
{
|
||||
|
||||
@@ -617,7 +617,6 @@ struct mm_struct {
|
||||
#ifdef CONFIG_IOMMU_SUPPORT
|
||||
u32 pasid;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LRU_GEN
|
||||
struct {
|
||||
/* this mm_struct is on lru_gen_mm_list */
|
||||
@@ -680,19 +679,20 @@ void lru_gen_migrate_mm(struct mm_struct *mm);
|
||||
static inline void lru_gen_init_mm(struct mm_struct *mm)
|
||||
{
|
||||
INIT_LIST_HEAD(&mm->lru_gen.list);
|
||||
nodes_clear(mm->lru_gen.nodes);
|
||||
#ifdef CONFIG_MEMCG
|
||||
mm->lru_gen.memcg = NULL;
|
||||
#endif
|
||||
nodes_clear(mm->lru_gen.nodes);
|
||||
}
|
||||
|
||||
static inline void lru_gen_use_mm(struct mm_struct *mm)
|
||||
{
|
||||
/* unlikely but not a bug when racing with lru_gen_migrate_mm() */
|
||||
VM_WARN_ON(list_empty(&mm->lru_gen.list));
|
||||
|
||||
if (!(current->flags & PF_KTHREAD) && !nodes_full(mm->lru_gen.nodes))
|
||||
nodes_setall(mm->lru_gen.nodes);
|
||||
/*
|
||||
* When the bitmap is set, page reclaim knows this mm_struct has been
|
||||
* used since the last time it cleared the bitmap. So it might be worth
|
||||
* walking the page tables of this mm_struct to clear the accessed bit.
|
||||
*/
|
||||
nodes_setall(mm->lru_gen.nodes);
|
||||
}
|
||||
|
||||
#else /* !CONFIG_LRU_GEN */
|
||||
|
||||
@@ -287,9 +287,9 @@ enum lruvec_flags {
|
||||
* Evictable pages are divided into multiple generations. The youngest and the
|
||||
* oldest generation numbers, max_seq and min_seq, are monotonically increasing.
|
||||
* They form a sliding window of a variable size [MIN_NR_GENS, MAX_NR_GENS]. An
|
||||
* offset within MAX_NR_GENS, gen, indexes the LRU list of the corresponding
|
||||
* generation. The gen counter in page->flags stores gen+1 while a page is on
|
||||
* one of lrugen->lists[]. Otherwise it stores 0.
|
||||
* offset within MAX_NR_GENS, i.e., gen, indexes the LRU list of the
|
||||
* corresponding generation. The gen counter in page->flags stores gen+1 while
|
||||
* a page is on one of lrugen->lists[]. Otherwise it stores 0.
|
||||
*
|
||||
* A page is added to the youngest generation on faulting. The aging needs to
|
||||
* check the accessed bit at least twice before handing this page over to the
|
||||
@@ -297,38 +297,42 @@ enum lruvec_flags {
|
||||
* fault; the second check makes sure this page hasn't been used since then.
|
||||
* This process, AKA second chance, requires a minimum of two generations,
|
||||
* hence MIN_NR_GENS. And to maintain ABI compatibility with the active/inactive
|
||||
* LRU, these two generations are considered active; the rest of generations, if
|
||||
* they exist, are considered inactive. See lru_gen_is_active(). PG_active is
|
||||
* always cleared while a page is on one of lrugen->lists[] so that the aging
|
||||
* needs not to worry about it. And it's set again when a page considered active
|
||||
* is isolated for non-reclaiming purposes, e.g., migration. See
|
||||
* lru_gen_add_page() and lru_gen_del_page().
|
||||
* LRU, e.g., /proc/vmstat, these two generations are considered active; the
|
||||
* rest of generations, if they exist, are considered inactive. See
|
||||
* lru_gen_is_active().
|
||||
*
|
||||
* MAX_NR_GENS is set to 4 so that the multi-gen LRU can support twice of the
|
||||
* categories of the active/inactive LRU when keeping track of accesses through
|
||||
* page tables. It requires order_base_2(MAX_NR_GENS+1) bits in page->flags.
|
||||
* PG_active is always cleared while a page is on one of lrugen->lists[] so that
|
||||
* the aging needs not to worry about it. And it's set again when a page
|
||||
* considered active is isolated for non-reclaiming purposes, e.g., migration.
|
||||
* See lru_gen_add_page() and lru_gen_del_page().
|
||||
*
|
||||
* MAX_NR_GENS is set to 4 so that the multi-gen LRU can support twice the
|
||||
* number of categories of the active/inactive LRU when keeping track of
|
||||
* accesses through page tables. This requires order_base_2(MAX_NR_GENS+1) bits
|
||||
* in page->flags.
|
||||
*/
|
||||
#define MIN_NR_GENS 2U
|
||||
#define MAX_NR_GENS 4U
|
||||
|
||||
/*
|
||||
* Each generation is divided into multiple tiers. Tiers represent different
|
||||
* ranges of numbers of accesses through file descriptors. A page accessed N
|
||||
* times through file descriptors is in tier order_base_2(N). A page in the
|
||||
* first tier (N=0,1) is marked by PG_referenced unless it was faulted in
|
||||
* though page tables or read ahead. A page in any other tier (N>1) is marked
|
||||
* by PG_referenced and PG_workingset.
|
||||
* Each generation is divided into multiple tiers. A page accessed N times
|
||||
* through file descriptors is in tier order_base_2(N). A page in the first tier
|
||||
* (N=0,1) is marked by PG_referenced unless it was faulted in through page
|
||||
* tables or read ahead. A page in any other tier (N>1) is marked by
|
||||
* PG_referenced and PG_workingset. This implies a minimum of two tiers is
|
||||
* supported without using additional bits in page->flags.
|
||||
*
|
||||
* In contrast to moving across generations which requires the LRU lock, moving
|
||||
* across tiers only requires operations on page->flags and therefore has a
|
||||
* negligible cost in the buffered access path. In the eviction path,
|
||||
* across tiers only involves atomic operations on page->flags and therefore
|
||||
* has a negligible cost in the buffered access path. In the eviction path,
|
||||
* comparisons of refaulted/(evicted+protected) from the first tier and the
|
||||
* rest infer whether pages accessed multiple times through file descriptors
|
||||
* are statistically hot and thus worth protecting.
|
||||
*
|
||||
* MAX_NR_TIERS is set to 4 so that the multi-gen LRU can support twice of the
|
||||
* categories of the active/inactive LRU when keeping track of accesses through
|
||||
* file descriptors. It requires MAX_NR_TIERS-2 additional bits in page->flags.
|
||||
* MAX_NR_TIERS is set to 4 so that the multi-gen LRU can support twice the
|
||||
* number of categories of the active/inactive LRU when keeping track of
|
||||
* accesses through file descriptors. This uses MAX_NR_TIERS-2 spare bits in
|
||||
* page->flags.
|
||||
*/
|
||||
#define MAX_NR_TIERS 4U
|
||||
|
||||
@@ -339,7 +343,6 @@ struct page_vma_mapped_walk;
|
||||
|
||||
#define LRU_GEN_MASK ((BIT(LRU_GEN_WIDTH) - 1) << LRU_GEN_PGOFF)
|
||||
#define LRU_REFS_MASK ((BIT(LRU_REFS_WIDTH) - 1) << LRU_REFS_PGOFF)
|
||||
#define LRU_REFS_FLAGS (BIT(PG_referenced) | BIT(PG_workingset))
|
||||
|
||||
#ifdef CONFIG_LRU_GEN
|
||||
|
||||
@@ -356,7 +359,7 @@ enum {
|
||||
};
|
||||
|
||||
#define MIN_LRU_BATCH BITS_PER_LONG
|
||||
#define MAX_LRU_BATCH (MIN_LRU_BATCH * 128)
|
||||
#define MAX_LRU_BATCH (MIN_LRU_BATCH * 64)
|
||||
|
||||
/* whether to keep historical stats from evicted generations */
|
||||
#ifdef CONFIG_LRU_GEN_STATS
|
||||
@@ -374,6 +377,9 @@ enum {
|
||||
* Normally anon and file min_seq are in sync. But if swapping is constrained,
|
||||
* e.g., out of swap space, file min_seq is allowed to advance and leave anon
|
||||
* min_seq behind.
|
||||
*
|
||||
* The number of pages in each generation is eventually consistent and therefore
|
||||
* can be transiently negative when reset_batch_size() is pending.
|
||||
*/
|
||||
struct lru_gen_struct {
|
||||
/* the aging increments the youngest generation number */
|
||||
@@ -382,9 +388,9 @@ struct lru_gen_struct {
|
||||
unsigned long min_seq[ANON_AND_FILE];
|
||||
/* the birth time of each generation in jiffies */
|
||||
unsigned long timestamps[MAX_NR_GENS];
|
||||
/* the multi-gen LRU lists */
|
||||
/* the multi-gen LRU lists, lazily sorted on eviction */
|
||||
struct list_head lists[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES];
|
||||
/* the sizes of the above lists */
|
||||
/* the multi-gen LRU sizes, eventually consistent */
|
||||
unsigned long nr_pages[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES];
|
||||
/* the exponential moving average of refaulted */
|
||||
unsigned long avg_refaulted[ANON_AND_FILE][MAX_NR_TIERS];
|
||||
@@ -400,27 +406,24 @@ struct lru_gen_struct {
|
||||
};
|
||||
|
||||
enum {
|
||||
MM_PTE_TOTAL, /* total leaf entries */
|
||||
MM_PTE_OLD, /* old leaf entries */
|
||||
MM_PTE_YOUNG, /* young leaf entries */
|
||||
MM_PMD_TOTAL, /* total non-leaf entries */
|
||||
MM_PMD_FOUND, /* non-leaf entries found in Bloom filters */
|
||||
MM_PMD_ADDED, /* non-leaf entries added to Bloom filters */
|
||||
MM_LEAF_TOTAL, /* total leaf entries */
|
||||
MM_LEAF_OLD, /* old leaf entries */
|
||||
MM_LEAF_YOUNG, /* young leaf entries */
|
||||
MM_NONLEAF_TOTAL, /* total non-leaf entries */
|
||||
MM_NONLEAF_FOUND, /* non-leaf entries found in Bloom filters */
|
||||
MM_NONLEAF_ADDED, /* non-leaf entries added to Bloom filters */
|
||||
NR_MM_STATS
|
||||
};
|
||||
|
||||
/* mnemonic codes for the mm stats above */
|
||||
#define MM_STAT_CODES "toydfa"
|
||||
|
||||
/* double-buffering Bloom filters */
|
||||
#define NR_BLOOM_FILTERS 2
|
||||
|
||||
struct lru_gen_mm_state {
|
||||
/* set to max_seq after each iteration */
|
||||
unsigned long seq;
|
||||
/* where the current iteration starts (inclusive) */
|
||||
/* where the current iteration continues (inclusive) */
|
||||
struct list_head *head;
|
||||
/* where the last iteration ends (exclusive) */
|
||||
/* where the last iteration ended (exclusive) */
|
||||
struct list_head *tail;
|
||||
/* to wait for the last page table walker to finish */
|
||||
struct wait_queue_head wait;
|
||||
@@ -439,7 +442,7 @@ struct lru_gen_mm_walk {
|
||||
unsigned long max_seq;
|
||||
/* the next address within an mm to scan */
|
||||
unsigned long next_addr;
|
||||
/* to batch page table entries */
|
||||
/* Unused -- for ABI compatibility */
|
||||
unsigned long bitmap[BITS_TO_LONGS(MIN_LRU_BATCH)];
|
||||
/* to batch promoted pages */
|
||||
int nr_pages[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES];
|
||||
|
||||
@@ -293,8 +293,7 @@ extern typeof(name) __mod_##type##__##name##_device_table \
|
||||
* files require multiple MODULE_FIRMWARE() specifiers */
|
||||
#define MODULE_FIRMWARE(_firmware) MODULE_INFO(firmware, _firmware)
|
||||
|
||||
#define _MODULE_IMPORT_NS(ns) MODULE_INFO(import_ns, #ns)
|
||||
#define MODULE_IMPORT_NS(ns) _MODULE_IMPORT_NS(ns)
|
||||
#define MODULE_IMPORT_NS(ns) MODULE_INFO(import_ns, __stringify(ns))
|
||||
|
||||
struct notifier_block;
|
||||
|
||||
|
||||
@@ -388,8 +388,10 @@ struct mtd_info {
|
||||
/* List of partitions attached to this MTD device */
|
||||
struct list_head partitions;
|
||||
|
||||
struct mtd_part part;
|
||||
struct mtd_master master;
|
||||
union {
|
||||
struct mtd_part part;
|
||||
struct mtd_master master;
|
||||
};
|
||||
};
|
||||
|
||||
static inline struct mtd_info *mtd_get_master(struct mtd_info *mtd)
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
#define SECTIONS_WIDTH 0
|
||||
#endif
|
||||
|
||||
#if ZONES_WIDTH + LRU_GEN_WIDTH + LRU_REFS_WIDTH + SECTIONS_WIDTH + NODES_SHIFT \
|
||||
#if ZONES_WIDTH + LRU_GEN_WIDTH + SECTIONS_WIDTH + NODES_SHIFT \
|
||||
<= BITS_PER_LONG - NR_PAGEFLAGS
|
||||
#define NODES_WIDTH NODES_SHIFT
|
||||
#elif defined(CONFIG_SPARSEMEM_VMEMMAP)
|
||||
@@ -90,7 +90,7 @@
|
||||
#define LAST_CPUPID_SHIFT 0
|
||||
#endif
|
||||
|
||||
#if ZONES_WIDTH + LRU_GEN_WIDTH + LRU_REFS_WIDTH + SECTIONS_WIDTH + NODES_WIDTH + \
|
||||
#if ZONES_WIDTH + LRU_GEN_WIDTH + SECTIONS_WIDTH + NODES_WIDTH + \
|
||||
KASAN_TAG_WIDTH + LAST_CPUPID_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS
|
||||
#define LAST_CPUPID_WIDTH LAST_CPUPID_SHIFT
|
||||
#else
|
||||
@@ -101,10 +101,15 @@
|
||||
#define LAST_CPUPID_NOT_IN_PAGE_FLAGS
|
||||
#endif
|
||||
|
||||
#if ZONES_WIDTH + LRU_GEN_WIDTH + LRU_REFS_WIDTH + SECTIONS_WIDTH + NODES_WIDTH + \
|
||||
#if ZONES_WIDTH + LRU_GEN_WIDTH + SECTIONS_WIDTH + NODES_WIDTH + \
|
||||
KASAN_TAG_WIDTH + LAST_CPUPID_WIDTH > BITS_PER_LONG - NR_PAGEFLAGS
|
||||
#error "Not enough bits in page flags"
|
||||
#endif
|
||||
|
||||
/* see the comment on MAX_NR_TIERS */
|
||||
#define LRU_REFS_WIDTH min(__LRU_REFS_WIDTH, BITS_PER_LONG - NR_PAGEFLAGS - \
|
||||
ZONES_WIDTH - LRU_GEN_WIDTH - SECTIONS_WIDTH - \
|
||||
NODES_WIDTH - KASAN_TAG_WIDTH - LAST_CPUPID_WIDTH)
|
||||
|
||||
#endif
|
||||
#endif /* _LINUX_PAGE_FLAGS_LAYOUT */
|
||||
|
||||
@@ -55,8 +55,8 @@ extern asmlinkage void schedule_tail(struct task_struct *prev);
|
||||
extern void init_idle(struct task_struct *idle, int cpu);
|
||||
|
||||
extern int sched_fork(unsigned long clone_flags, struct task_struct *p);
|
||||
extern void sched_post_fork(struct task_struct *p,
|
||||
struct kernel_clone_args *kargs);
|
||||
extern void sched_cgroup_fork(struct task_struct *p, struct kernel_clone_args *kargs);
|
||||
extern void sched_post_fork(struct task_struct *p);
|
||||
extern void sched_dead(struct task_struct *p);
|
||||
|
||||
void __noreturn do_task_dead(void);
|
||||
|
||||
@@ -1436,6 +1436,11 @@ static inline unsigned int skb_end_offset(const struct sk_buff *skb)
|
||||
{
|
||||
return skb->end;
|
||||
}
|
||||
|
||||
static inline void skb_set_end_offset(struct sk_buff *skb, unsigned int offset)
|
||||
{
|
||||
skb->end = offset;
|
||||
}
|
||||
#else
|
||||
static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
|
||||
{
|
||||
@@ -1446,6 +1451,11 @@ static inline unsigned int skb_end_offset(const struct sk_buff *skb)
|
||||
{
|
||||
return skb->end - skb->head;
|
||||
}
|
||||
|
||||
static inline void skb_set_end_offset(struct sk_buff *skb, unsigned int offset)
|
||||
{
|
||||
skb->end = skb->head + offset;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Internal */
|
||||
@@ -1665,19 +1675,19 @@ static inline int skb_unclone(struct sk_buff *skb, gfp_t pri)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This variant of skb_unclone() makes sure skb->truesize is not changed */
|
||||
/* This variant of skb_unclone() makes sure skb->truesize
|
||||
* and skb_end_offset() are not changed, whenever a new skb->head is needed.
|
||||
*
|
||||
* Indeed there is no guarantee that ksize(kmalloc(X)) == ksize(kmalloc(X))
|
||||
* when various debugging features are in place.
|
||||
*/
|
||||
int __skb_unclone_keeptruesize(struct sk_buff *skb, gfp_t pri);
|
||||
static inline int skb_unclone_keeptruesize(struct sk_buff *skb, gfp_t pri)
|
||||
{
|
||||
might_sleep_if(gfpflags_allow_blocking(pri));
|
||||
|
||||
if (skb_cloned(skb)) {
|
||||
unsigned int save = skb->truesize;
|
||||
int res;
|
||||
|
||||
res = pskb_expand_head(skb, 0, 0, pri);
|
||||
skb->truesize = save;
|
||||
return res;
|
||||
}
|
||||
if (skb_cloned(skb))
|
||||
return __skb_unclone_keeptruesize(skb, pri);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -355,7 +355,6 @@ extern void lru_add_drain_cpu(int cpu);
|
||||
extern void lru_add_drain_cpu_zone(struct zone *zone);
|
||||
extern void lru_add_drain_all(void);
|
||||
extern void rotate_reclaimable_page(struct page *page);
|
||||
extern void activate_page(struct page *page);
|
||||
extern void deactivate_file_page(struct page *page);
|
||||
extern void deactivate_page(struct page *page);
|
||||
extern void mark_page_lazyfree(struct page *page);
|
||||
|
||||
22
include/trace/hooks/buffer.h
Normal file
22
include/trace/hooks/buffer.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM buffer
|
||||
|
||||
#define TRACE_INCLUDE_PATH trace/hooks
|
||||
|
||||
#if !defined(_TRACE_HOOK_BUFFER_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _TRACE_HOOK_BUFFER_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <trace/hooks/vendor_hooks.h>
|
||||
|
||||
DECLARE_HOOK(android_vh_bh_lru_install,
|
||||
TP_PROTO(struct page *page, bool *flush),
|
||||
TP_ARGS(page, flush));
|
||||
|
||||
/* macro versions of hooks are no longer required */
|
||||
|
||||
#endif /* _TRACE_HOOK_BUFFER_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
#include <trace/define_trace.h>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user