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.

29c427664a Merge tag 'android13-5.10.149_r00' into android13-5.10
70be865521 ANDROID: Update the ABI representation
57e680a1a8 ANDROID: Sched: Add restricted vendor hook in update_misfit_status()
64b7606115 ANDROID: Sched: Add restricted vendor hook in schedule()
ef815ee856 ANDROID: Sched: Add restricted vendor hook in wake_up_new_task()
b7dbea10b1 ANDROID: Fix license for BUILD.bazel file.
c45168c6c2 ANDROID: kleaf: load() then package().
2ff20aeeb6 ANDROID: update the .xml ABI file due to LTS changes.
887fa8f059 Revert "mtd: fix 'part' field data corruption in mtd_info"
e6a51ad94c Revert "audit: log AUDIT_TIME_* records only from rules"
cac3a605c5 Merge 64f18041dd ("Merge branch 'android13-5.10' into branch 'android13-5.10-lts'") into android13-5.10-lts
cc59c47abb ANDROID: GKI: rockchip: Enable symbols for charger and battery
fd1290ee6c ANDROID: GKI: MGLRU ABI Fixup
e0f24fb5c6 ANDROID: GKI: Build multi-gen LRU
92c47e2a15 ANDROID: Make MGLRU aware of speculative faults
9d5b3a1547 BACKPORT: mm: multi-gen LRU: design doc
ee101878a8 UPSTREAM: mm: multi-gen LRU: admin guide
86b889811d BACKPORT: mm: multi-gen LRU: debugfs interface
3369bf02b2 UPSTREAM: mm: multi-gen LRU: thrashing prevention
e9983679e7 BACKPORT: mm: multi-gen LRU: kill switch
e4ed637282 BACKPORT: mm: multi-gen LRU: optimize multiple memcgs
c2869b6c22 BACKPORT: mm: multi-gen LRU: support page table walks
fd80133d8c BACKPORT: mm: multi-gen LRU: exploit locality in rmap
8455e88fe4 BACKPORT: mm: multi-gen LRU: minimal implementation
278f56801a BACKPORT: mm: multi-gen LRU: groundwork
245ea1de3e BACKPORT: mm/vmscan.c: refactor shrink_node()
4ccde30ac9 BACKPORT: mm: x86: add CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG
f04c2fbac2 BACKPORT: mm: x86, arm64: add arch_has_hw_pte_young()
691008625e Revert "FROMLIST: mm: x86, arm64: add arch_has_hw_pte_young()"
4741bcbac4 Revert "FROMLIST: mm: x86: add CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG"
a38ef3be2b Revert "FROMLIST: mm/vmscan.c: refactor shrink_node()"
ead7512d05 Revert "FROMLIST: mm: multi-gen LRU: groundwork"
b61dbc579b Revert "FROMLIST: mm: multi-gen LRU: minimal implementation"
7a2929e68c Revert "FROMLIST: mm: multi-gen LRU: exploit locality in rmap"
db1832bb7c Revert "FROMLIST: mm: multi-gen LRU: support page table walks"
6fa2a68b43 Revert "FROMLIST: mm: multi-gen LRU: optimize multiple memcgs"
56c66e7cc4 Revert "FROMLIST: mm: multi-gen LRU: kill switch"
06e6006a04 Revert "FROMLIST: mm: multi-gen LRU: thrashing prevention"
0d9f7bf39c Revert "FROMLIST: mm: multi-gen LRU: debugfs interface"
43c49618c8 Revert "FROMLIST: mm: multi-gen LRU: admin guide"
3676a0c29a Revert "FROMLIST: mm: multi-gen LRU: design doc"
66f2c69836 Revert "ANDROID: GKI: build multi-gen LRU"
40dd81e34c Revert "ANDROID: Make MGLRU aware of speculative faults"
baa23246e9 UPSTREAM: binder: Gracefully handle BINDER_TYPE_FDA objects with num_fds=0
3d213a626d UPSTREAM: binder: Address corner cases in deferred copy and fixup
9d1efccf5e UPSTREAM: binder: fix pointer cast warning
b83173bf86 UPSTREAM: binder: defer copies of pre-patched txn data
aaf2369717 UPSTREAM: binder: read pre-translated fds from sender buffer
ecf61e4e11 UPSTREAM: binder: avoid potential data leakage when copying txn
3767674eac ANDROID: khugepaged: fix mixing declarations warning in retract_page_tables
c440edc7a2 ANDROID: mm: fix build issue in spf when CONFIG_USERFAULTFD=n
2a62463d6e UPSTREAM: f2fs: don't use casefolded comparison for "." and ".."
c63efa6751 UPSTREAM: regulator: scmi: Fix refcount leak in scmi_regulator_probe
9b8948cb0e UPSTREAM: KVM: arm64: vgic-v3: Consistently populate ID_AA64PFR0_EL1.GIC
3bba44a8c3 UPSTREAM: block/mq-deadline: Set the fifo_time member also if inserting at head
49823ad276 BACKPORT: Revert "mm/cma.c: remove redundant cma_mutex lock"
fb3cba1815 UPSTREAM: module.h: simplify MODULE_IMPORT_NS
9257ade3bc UPSTREAM: procfs: prevent unprivileged processes accessing fdinfo dir
ae1f81f7f4 UPSTREAM: KVM: arm64: nvhe: Eliminate kernel-doc warnings
17d733d05b UPSTREAM: iommu/mediatek: Add mutex for m4u_group and m4u_dom in data
b66bdceff1 UPSTREAM: iommu/mediatek: Remove clk_disable in mtk_iommu_remove
c19e8027fe UPSTREAM: iommu/mediatek: Fix 2 HW sharing pgtable issue
80b363ae64 UPSTREAM: mm: hugetlb: add missing cache flushing in hugetlb_unshare_all_pmds()
4d39f905f5 UPSTREAM: firmware: arm_ffa: Remove incorrect assignment of driver_data
d57c415ab0 UPSTREAM: firmware: arm_ffa: Fix uuid parameter to ffa_partition_probe
dba02a021a UPSTREAM: selftests/damon: add damon to selftests root Makefile
9e059fe061 BACKPORT: KVM: arm64: Actually prevent SMC64 SYSTEM_RESET2 from AArch32
c6408580e1 UPSTREAM: KVM: arm64: Generally disallow SMC64 for AArch32 guests
1eed68cdc9 UPSTREAM: irqchip/gic-v4: Wait for GICR_VPENDBASER.Dirty to clear before descheduling
968c524ded UPSTREAM: virtio: use virtio_device_ready() in virtio_device_restore()
9eaf45a22b UPSTREAM: mm: kfence: fix missing objcg housekeeping for SLAB
7923c77f8f UPSTREAM: fs: erofs: add sanity check for kobject in erofs_unregister_sysfs
e7bbb89470 UPSTREAM: clk: Fix clk_hw_get_clk() when dev is NULL
69914efc9b UPSTREAM: arm64: kasan: fix include error in MTE functions
2be9d2b296 UPSTREAM: arm64: prevent instrumentation of bp hardening callbacks
2917f48bdb UPSTREAM: PM: domains: Fix sleep-in-atomic bug caused by genpd_debug_remove()
d9612d6109 UPSTREAM: mm: fix use-after-free bug when mm->mmap is reused after being freed
3b68c1140f UPSTREAM: kasan: test: prevent cache merging in kmem_cache_double_destroy
d27c600b42 BACKPORT: vsprintf: Fix %pK with kptr_restrict == 0
75a8a2c657 ANDROID: KVM: arm64: Use 32-bit function ID for PSCI MEM_PROTECT call
24ba7e97d3 UPSTREAM: efi: capsule-loader: Fix use-after-free in efi_capsule_write
d2426b0692 UPSTREAM: net: preserve skb_end_offset() in skb_unclone_keeptruesize()
2ea1a8c467 BACKPORT: net: add skb_set_end_offset() helper
7d40247c5b UPSTREAM: arm64: Correct wrong label in macro __init_el2_gicv3
cb515c669c UPSTREAM: KVM: arm64: Stop handle_exit() from handling HVC twice when an SError occurs
316b7560ab UPSTREAM: KVM: arm64: Avoid consuming a stale esr value when SError occur
e3e5b3b856 UPSTREAM: usb: typec: tcpm: Do not disconnect when receiving VSAFE0V
2317bc5306 UPSTREAM: usb: typec: tcpci: don't touch CC line if it's Vconn source
8f2ac1deb1 UPSTREAM: dt-bindings: memory: mtk-smi: Correct minItems to 2 for the gals clocks
72decd9765 BACKPORT: dt-bindings: memory: mtk-smi: No need mediatek,larb-id for mt8167
33e4819112 BACKPORT: dt-bindings: memory: mtk-smi: Rename clock to clocks
851451819e UPSTREAM: dma-buf: cma_heap: Fix mutex locking section
c8f988d00d UPSTREAM: scsi: core: Declare 'scsi_scan_type' static
f3fe2dacb0 UPSTREAM: scsi: core: Suppress a kernel-doc warning
17b50edfad UPSTREAM: dma-buf: DMABUF_SYSFS_STATS should depend on DMA_SHARED_BUFFER
4ececb4ebd UPSTREAM: clk: versatile: Depend on HAS_IOMEM
9b70ff660f BACKPORT: arm64: meson: select COMMON_CLK
05fbbf0d13 UPSTREAM: tools: do not include scripts/Kbuild.include
924872e549 UPSTREAM: kbuild: dummy-tools: adjust to scripts/cc-version.sh
252e42f395 UPSTREAM: kbuild: do not include include/config/auto.conf from adjust_autoksyms.sh
b9a8323fde UPSTREAM: scsi: docs: ABI: sysfs-driver-ufs: Add DeepSleep power mode
26369cdee4 ANDROID: gki_defconfig: enable CONFIG_USB_CONFIGFS_F_UVC
0481654d9f ANDROID: mm: disable speculative page faults for CONFIG_NUMA
f6ddc1c41e ANDROID: mm: fix invalid backport in speculative page fault path
c3f0fd7976 ANDROID: disable page table moves when speculative page faults are enabled
3d3b77c9c0 ANDROID: mm: assert that mmap_lock is taken exclusively in vm_write_begin
df62da3909 ANDROID: mm: remove sequence counting when mmap_lock is not exclusively owned
66544e79f4 ANDROID: mm/khugepaged: add missing vm_write_{begin|end}
2a3979df04 BACKPORT: FROMLIST: mm: implement speculative handling in filemap_fault()
ec35e912e7 ANDROID: mm: prevent reads of unstable pmd during speculation
ce7fa7020a ANDROID: mm: prevent speculative page fault handling for in do_swap_page()
4812532ece ANDROID: mm: prevent speculative page fault handling for userfaults
43247cf563 ANDROID: mm: skip pte_alloc during speculative page fault
2f2dc42fbf ANDROID: GKI: rockchip: Add symbols for cpufreq
c8f45c4915 ANDROID: Update the ABI representation
0fabf2342f ANDROID: sched: add hook point in do_sched_yield()
2aed2a7cb0 ANDROID: KVM: arm64: s2mpu: Fix SYNC latency regression
e1ea4666e1 ANDROID: KVM: arm64: iommu: Add host_stage2_idmap_complete
15e65b4a22 ANDROID: KVM: arm64: Issue CMOs when tearing down shadow pages
80fcf382d1 ANDROID: Add ashmem ioctl to return a unique file identifier
056ee87d05 ANDROID: Update the ABI representation
b6cfd9d69f ANDROID: KVM: arm64: Fix repainting of PSCI SYSTEM_RESET2 calls
03b60942fe ANDROID: Update the ABI representation
d08c3d3ba2 ANDROID: Update the ABI representation
01645da2f5 ANDROID: Update the ABI representation
6c86db3f70 ANDROID: Update the ABI representation
db144888f8 ANDROID: kernel: sched: Export reweight_task
6f642cd2f2 FROMGIT: f2fs: allow to read node block after shutdown
92a7e867cf FROMGIT: usb: core: stop USB enumeration if too many retries
f3fe2e6612 ANDROID: KVM: arm64: Adjust PSCI MEM_PROTECT refcount across share/unshare
e7b635a520 BACKPORT: ext4,f2fs: fix readahead of verity data
c57ed31850 ANDROID: Update the ABI representation
bcf1e503f5 ANDROID: adjust vendor hook to control blk_plug
6cbaa88f4a ANDROID: dm-user: Remove bio recount in I/O path
69e2e9275b ANDROID: Update the ABI representation
501eeee6e2 UPSTREAM: irqchip/tegra: Fix overflow implicit truncation warnings
13a5e047bd UPSTREAM: drm/meson: Fix overflow implicit truncation warnings
55a2910224 UPSTREAM: video: fbdev: pxa3xx-gcu: Fix integer overflow in pxa3xx_gcu_write
52e7aa3245 FROMLIST: KVM: arm64: pkvm: Fixup boot mode to reflect that the kernel resumes from EL1
bcb19fa296 ANDROID: GKI: Add symbol list for exynos
9e3ae1fbd3 UPSTREAM: sched: Fix yet more sched_fork() races
3de7d142cf BACKPORT: KVM: arm64: Fix bad dereference on MTE-enabled systems
b684150a44 FROMLIST: binder: fix UAF of alloc->vma in race with munmap()
9ffd177dce ANDROID: Update the ABI representation
89fed37332 ANDROID: vendor hook to control blk_plug for shrink_lruvec
c0ce22abf7 UPSTREAM: mm: Fix TLB flush for not-first PFNMAP mappings in unmap_region()
75c194cf1a UPSTREAM: af_key: Do not call xfrm_probe_algs in parallel
8812ab3f9d UPSTREAM: mm: Force TLB flush for PFNMAP mappings before unlink_file_vma()
4e97b7ff2b ANDROID: KVM: arm64: Donate memory per vcpu for each vcpu shadow state
6a7700c5b5 ANDROID: KVM: arm64: Initialize shadow vcpus with separate hypercalls
0b7f3b9652 ANDROID: KVM: arm64: Refactor unpinning host vcpu
d345371dd2 ANDROID: KVM: arm64: Separate functions for shadow vm and vcpu init
66be6be8fb ANDROID: KVM: arm64: Refactor code for reclaiming guest memory into a function
232bdcbd66 ANDROID: pass argument in zap_pte_range vendor hooks
a83ef907f0 ANDROID: GKI: Add for rockchip platform basic symbol
05c1e5a6fd ANDROID: GKI: Add Bazel rockchip symbol list entry
56e639d3ff ANDROID: sched: check on_rq in freezer_should_skip()
90a47b6250 ANDROID: Update the ABI representation
14c8176992 ANDROID: KVM: arm64: Only unpin a vCPU SVE state if set
559e6700c3 ANDROID: Update the ABI representation
9966a706d1 FROMGIT: f2fs: let's avoid to get cp_rwsem twice by f2fs_evict_inode by d_invalidate
86d2835139 ANDROID: Update the ABI representation
a17e132ec4 ANDROID: vendor hook to control blk_plug for memory reclaim
1c741865f4 ANDROID: Update the ABI representation
6c543641c6 UPSTREAM: wifi: mac80211: fix MBSSID parsing use-after-free
187e6dad2a UPSTREAM: wifi: mac80211: don't parse mbssid in assoc response
12bd079b61 UPSTREAM: mac80211: mlme: find auth challenge directly
13c3ed22fe UPSTREAM: wifi: cfg80211: update hidden BSSes to avoid WARN_ON
4bff45998e UPSTREAM: wifi: mac80211: fix crash in beacon protection for P2P-device
7e9ccb517a UPSTREAM: wifi: mac80211_hwsim: avoid mac80211 warning on bad rate
88b3da7668 UPSTREAM: wifi: cfg80211: avoid nontransmitted BSS list corruption
1e18328c84 UPSTREAM: wifi: cfg80211: fix BSS refcounting bugs
d56839bb09 UPSTREAM: wifi: cfg80211: ensure length byte is present before access
d96c2b5944 UPSTREAM: wifi: cfg80211/mac80211: reject bad MBSSID elements
4ae8e2c20f UPSTREAM: wifi: cfg80211: fix u8 overflow in cfg80211_update_notlisted_nontrans()
6e0df30312 ANDROID: Update the ABI representation
74e2ea264c ANDROID: vendor hook to control bh_lru and lru_cache_disable
f45d10e83b ANDROID: Update the ABI representation
d257ef6764 ANDROID: vendor hook for TLB batching control
2823b3889d UPSTREAM: fbcon: Prevent that screen size is smaller than font size
739b963eb8 UPSTREAM: fbcon: Disallow setting font bigger than screen size
cf3742cba4 UPSTREAM: fbmem: Check virtual screen sizes in fb_set_var()
788ba5e9de ANDROID: GKI: Add build for rockchip platform
90db4c38b9 ANDROID: Update the ABI representation
2f8253b7e6 ANDROID: vendor hook to control pagevec flush
992b5f98ca ANDROID: KVM: arm64: s2mpu: Add SysMMU_SYNC timeout
19424168db ANDROID: KVM: arm64: Force CMOs with FWB when reclaiming guest pages
f177a280b1 ANDROID: KVM: arm64: Fix MMIO guard map error handling
32bef95f91 UPSTREAM: psi: Fix psi state corruption when schedule() races with cgroup move
e4c738dd13 ANDROID: Update the ABI representation
07e046b996 BACKPORT: HID: steam: Prevent NULL pointer dereference in steam_{recv,send}_report
b366878684 ANDROID: KVM: arm64: Fix MMIO guard unmap
befd3e393e UPSTREAM: crypto: jitter - add oversampling of noise source
6ed90e9805 ANDROID: Update the ABI representation
9a8b45a9e4 FROMGIT: 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:
Greg Kroah-Hartman
2022-12-01 17:00:29 +00:00
140 changed files with 20687 additions and 8965 deletions

View File

@@ -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",
]

View File

@@ -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>

View File

@@ -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

View File

@@ -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.

View File

@@ -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.

View File

@@ -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

View File

@@ -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:

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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,

View File

@@ -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__

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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);
/*

View File

@@ -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);

View File

@@ -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);

View File

@@ -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),

View File

@@ -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);
}
}

View File

@@ -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),
};

View File

@@ -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();
}

View File

@@ -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:

View File

@@ -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:

View File

@@ -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

View File

@@ -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:

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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
View 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}"

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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,

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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"

View File

@@ -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.

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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];
};

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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)

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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. */

View File

@@ -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;

View File

@@ -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,
};

View File

@@ -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, &reg);
if (ret < 0)
return ret;
vconn_pres = !!(reg & TCPC_POWER_STATUS_VCONN_PRES);
if (vconn_pres) {
ret = regmap_read(tcpci->regmap, TCPC_TCPC_CTRL, &reg);
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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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) &&

View File

@@ -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)

View File

@@ -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);

View File

@@ -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:

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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:

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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)

View File

@@ -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,

View File

@@ -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;

View File

@@ -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(&current->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
}
/*

View File

@@ -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.

View File

@@ -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)
{

View File

@@ -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 */

View File

@@ -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];

View File

@@ -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;

View File

@@ -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)

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View 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