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: 228815136
Change-Id: Id41a25fd15c5b71f8064f1c7d9cac9560fcdde85
Signed-off-by: Vivek Kumar <quic_vivekuma@quicinc.com>
Signed-off-by: Shreyas K K <quic_shrekk@quicinc.com>
This commit is contained in:
Shreyas K K
2022-10-07 22:12:28 +05:30
committed by Treehugger Robot
parent c297152a18
commit d2cb755a43
5 changed files with 52 additions and 2 deletions

View File

@@ -37,6 +37,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
@@ -87,6 +88,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)
@@ -124,6 +127,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);

View File

@@ -105,6 +105,7 @@
#include <trace/hooks/evdev.h>
#include <trace/hooks/signal.h>
#include <trace/hooks/cfg80211.h>
#include <trace/hooks/bl_hib.h>
/*
* Export tracepoints that act as a bare tracehook (ie: have no trace event
@@ -397,6 +398,9 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_pages_failure_bypass);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_cpufreq_acct_update_power);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rmqueue);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_tune_inactive_ratio);
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);
/*
* For type visibility

View 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 block_device;
DECLARE_HOOK(android_vh_check_hibernation_swap,
TP_PROTO(struct block_device *resume_block, bool *hib_swap),
TP_ARGS(resume_block, 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 block_device *hib_resume_bdev),
TP_ARGS(hib_resume_bdev));
#endif /* _TRACE_HOOK_S2D_H */
/* This part must be outside protection */
#include <trace/define_trace.h>

View File

@@ -31,6 +31,7 @@
#include <linux/kthread.h>
#include <linux/crc32.h>
#include <linux/ktime.h>
#include <trace/hooks/bl_hib.h>
#include "power.h"
@@ -1527,6 +1528,7 @@ int swsusp_check(void)
FMODE_READ | FMODE_EXCL, &holder);
if (!IS_ERR(hib_resume_bdev)) {
set_blocksize(hib_resume_bdev, PAGE_SIZE);
trace_android_vh_save_hib_resume_bdev(hib_resume_bdev);
clear_page(swsusp_header);
error = hib_submit_io(REQ_OP_READ, 0,
swsusp_resume_block,

View File

@@ -44,6 +44,7 @@
#include <asm/tlbflush.h>
#include <linux/swapops.h>
#include <linux/swap_cgroup.h>
#include <trace/hooks/bl_hib.h>
static bool swap_count_continued(struct swap_info_struct *, pgoff_t,
unsigned char);
@@ -2527,6 +2528,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
struct filename *pathname;
int err, found = 0;
unsigned int old_block_size;
bool hibernation_swap = false;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -2616,10 +2618,14 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
flush_work(&p->discard_work);
destroy_swap_extents(p);
trace_android_vh_check_hibernation_swap(p->bdev, &hibernation_swap);
if (p->flags & SWP_CONTINUED)
free_swap_count_continuations(p);
if (!p->bdev || !blk_queue_nonrot(bdev_get_queue(p->bdev)))
if (!p->bdev || hibernation_swap ||
!blk_queue_nonrot(bdev_get_queue(p->bdev)))
atomic_dec(&nr_rotate_swap);
mutex_lock(&swapon_mutex);
@@ -3143,6 +3149,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
struct page *page = NULL;
struct inode *inode = NULL;
bool inced_nr_rotate_swap = false;
bool hibernation_swap = false;
if (swap_flags & ~SWAP_FLAGS_VALID)
return -EINVAL;
@@ -3218,13 +3225,16 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
goto bad_swap_unlock_inode;
}
trace_android_vh_check_hibernation_swap(p->bdev, &hibernation_swap);
if (p->bdev && blk_queue_stable_writes(p->bdev->bd_disk->queue))
p->flags |= SWP_STABLE_WRITES;
if (p->bdev && p->bdev->bd_disk->fops->rw_page)
p->flags |= SWP_SYNCHRONOUS_IO;
if (p->bdev && blk_queue_nonrot(bdev_get_queue(p->bdev))) {
if (p->bdev && !hibernation_swap &&
blk_queue_nonrot(bdev_get_queue(p->bdev))) {
int cpu;
unsigned long ci, nr_cluster;