ANDROID: vendor hooks: Add hooks to support bootloader based hibernation
Add vendor hooks to disable randomization of swap slot allocation for swap partition used for saving hibernation image. Another level of randomization of swap slots takes place at the firmware level as well in order to address the wear leveling for UFS/MMC devices, so this vendor hook checks if a block device represents the swap partition being used for saving hibernation image, if yes, the swap slot allocation for such partition is serialized at kernel level. There is a performance advantage of reading contiguous pages of hibernation image, it makes the restore logic of hibernation image simpler and faster as there are no seeks involved in the secondary storage to read multiple contiguous pages of the image. Bug: 379617660 Change-Id: Id41a25fd15c5b71f8064f1c7d9cac9560fcdde85 Signed-off-by: Vivek Kumar <quic_vivekuma@quicinc.com> Signed-off-by: Shreyas K K <quic_shrekk@quicinc.com> Signed-off-by: Auditya Bhattaram <quic_audityab@quicinc.com>
This commit is contained in:
committed by
Treehugger Robot
parent
2b6b7a90c8
commit
4f8ffa0f05
@@ -33,6 +33,7 @@
|
||||
#include <asm/sysreg.h>
|
||||
#include <asm/trans_pgd.h>
|
||||
#include <asm/virt.h>
|
||||
#include <trace/hooks/bl_hib.h>
|
||||
|
||||
/*
|
||||
* Hibernate core relies on this value being 0 on resume, and marks it
|
||||
@@ -80,6 +81,8 @@ static struct arch_hibernate_hdr {
|
||||
phys_addr_t __hyp_stub_vectors;
|
||||
|
||||
u64 sleep_cpu_mpidr;
|
||||
|
||||
ANDROID_VENDOR_DATA(1);
|
||||
} resume_hdr;
|
||||
|
||||
static inline void arch_hdr_invariants(struct arch_hibernate_hdr_invariants *i)
|
||||
@@ -116,6 +119,9 @@ int arch_hibernation_header_save(void *addr, unsigned int max_size)
|
||||
hdr->ttbr1_el1 = __pa_symbol(swapper_pg_dir);
|
||||
hdr->reenter_kernel = _cpu_resume;
|
||||
|
||||
trace_android_vh_save_cpu_resume(&hdr->android_vendor_data1,
|
||||
__pa(cpu_resume));
|
||||
|
||||
/* We can't use __hyp_get_vectors() because kvm may still be loaded */
|
||||
if (el2_reset_needed())
|
||||
hdr->__hyp_stub_vectors = __pa_symbol(__hyp_stub_vectors);
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <trace/hooks/fault.h>
|
||||
#include <trace/hooks/topology.h>
|
||||
#include <trace/hooks/rwsem.h>
|
||||
#include <trace/hooks/bl_hib.h>
|
||||
|
||||
/*
|
||||
* Export tracepoints that act as a bare tracehook (ie: have no trace event
|
||||
@@ -155,3 +156,6 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_downgrade_wake_finish);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_wake_finish);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alter_mutex_list_add);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mutex_unlock_slowpath);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_check_hibernation_swap);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_save_cpu_resume);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_save_hib_resume_bdev);
|
||||
|
||||
28
include/trace/hooks/bl_hib.h
Normal file
28
include/trace/hooks/bl_hib.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM bl_hib
|
||||
|
||||
#define TRACE_INCLUDE_PATH trace/hooks
|
||||
|
||||
#if !defined(_TRACE_HOOK_S2D_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _TRACE_HOOK_S2D_H
|
||||
|
||||
#include <trace/hooks/vendor_hooks.h>
|
||||
|
||||
struct file;
|
||||
|
||||
DECLARE_HOOK(android_vh_check_hibernation_swap,
|
||||
TP_PROTO(struct file *resume_block_file, bool *hib_swap),
|
||||
TP_ARGS(resume_block_file, hib_swap));
|
||||
|
||||
DECLARE_HOOK(android_vh_save_cpu_resume,
|
||||
TP_PROTO(u64 *addr, u64 phys_addr),
|
||||
TP_ARGS(addr, phys_addr));
|
||||
|
||||
DECLARE_HOOK(android_vh_save_hib_resume_bdev,
|
||||
TP_PROTO(struct file *hib_resume_bdev_file),
|
||||
TP_ARGS(hib_resume_bdev_file));
|
||||
|
||||
#endif /* _TRACE_HOOK_S2D_H */
|
||||
/* This part must be outside protection */
|
||||
#include <trace/define_trace.h>
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <trace/hooks/bl_hib.h>
|
||||
|
||||
#include "power.h"
|
||||
|
||||
@@ -1569,6 +1570,7 @@ int swsusp_check(bool exclusive)
|
||||
hib_resume_bdev_file = bdev_file_open_by_dev(swsusp_resume_device,
|
||||
BLK_OPEN_READ, holder, NULL);
|
||||
if (!IS_ERR(hib_resume_bdev_file)) {
|
||||
trace_android_vh_save_hib_resume_bdev(hib_resume_bdev_file);
|
||||
clear_page(swsusp_header);
|
||||
error = hib_submit_io(REQ_OP_READ, swsusp_resume_block,
|
||||
swsusp_header, NULL);
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <linux/swap_cgroup.h>
|
||||
#include "internal.h"
|
||||
#include "swap.h"
|
||||
#include <trace/hooks/bl_hib.h>
|
||||
|
||||
static bool swap_count_continued(struct swap_info_struct *, pgoff_t,
|
||||
unsigned char);
|
||||
@@ -2728,6 +2729,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
|
||||
struct inode *inode;
|
||||
struct filename *pathname;
|
||||
int err, found = 0;
|
||||
bool hibernation_swap = false;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
@@ -2818,10 +2820,13 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
|
||||
flush_work(&p->discard_work);
|
||||
|
||||
destroy_swap_extents(p);
|
||||
|
||||
trace_android_vh_check_hibernation_swap(p->swap_file, &hibernation_swap);
|
||||
|
||||
if (p->flags & SWP_CONTINUED)
|
||||
free_swap_count_continuations(p);
|
||||
|
||||
if (!p->bdev || !bdev_nonrot(p->bdev))
|
||||
if (!p->bdev || hibernation_swap || !bdev_nonrot(p->bdev))
|
||||
atomic_dec(&nr_rotate_swap);
|
||||
|
||||
mutex_lock(&swapon_mutex);
|
||||
@@ -3361,6 +3366,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
|
||||
struct folio *folio = NULL;
|
||||
struct inode *inode = NULL;
|
||||
bool inced_nr_rotate_swap = false;
|
||||
bool hibernation_swap = false;
|
||||
|
||||
if (swap_flags & ~SWAP_FLAGS_VALID)
|
||||
return -EINVAL;
|
||||
@@ -3440,6 +3446,8 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
|
||||
if (error)
|
||||
goto bad_swap_unlock_inode;
|
||||
|
||||
trace_android_vh_check_hibernation_swap(si->swap_file, &hibernation_swap);
|
||||
|
||||
nr_extents = setup_swap_map_and_extents(si, swap_header, swap_map,
|
||||
maxpages, &span);
|
||||
if (unlikely(nr_extents < 0)) {
|
||||
@@ -3464,7 +3472,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
|
||||
if (si->bdev && bdev_synchronous(si->bdev))
|
||||
si->flags |= SWP_SYNCHRONOUS_IO;
|
||||
|
||||
if (si->bdev && bdev_nonrot(si->bdev)) {
|
||||
if (si->bdev && !hibernation_swap && bdev_nonrot(si->bdev)) {
|
||||
si->flags |= SWP_SOLIDSTATE;
|
||||
|
||||
cluster_info = setup_clusters(si, swap_header, maxpages);
|
||||
|
||||
Reference in New Issue
Block a user