diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c index 788597a6b6a2..2ea6bc542101 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c @@ -33,6 +33,7 @@ #include #include #include +#include /* * 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) @@ -117,6 +120,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); diff --git a/drivers/android/vendor_hooks.c b/drivers/android/vendor_hooks.c index 1df1f21fb156..481f11a67e29 100644 --- a/drivers/android/vendor_hooks.c +++ b/drivers/android/vendor_hooks.c @@ -65,6 +65,7 @@ #include #include #include +#include /* * Export tracepoints that act as a bare tracehook (ie: have no trace event @@ -293,3 +294,6 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_process_madvise_end); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_smaps_pte_entry); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_show_smap); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_ctl_dirty_rate); +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); diff --git a/include/trace/hooks/bl_hib.h b/include/trace/hooks/bl_hib.h new file mode 100644 index 000000000000..f47f3760ffe4 --- /dev/null +++ b/include/trace/hooks/bl_hib.h @@ -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_BL_HIB_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_HOOK_BL_HIB_H + +#include + +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_BL_HIB_H */ +/* This part must be outside protection */ +#include diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 0973c628022d..d55b2c949c94 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "power.h" @@ -1524,6 +1525,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, swsusp_resume_block, swsusp_header, NULL); diff --git a/mm/swapfile.c b/mm/swapfile.c index b63e7fd3d6c6..ce706c4a9b38 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -46,6 +46,7 @@ #include #include #include "swap.h" +#include static bool swap_count_continued(struct swap_info_struct *, pgoff_t, unsigned char); @@ -2399,6 +2400,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; @@ -2488,10 +2490,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 || !bdev_nonrot(p->bdev)) + if (!p->bdev || hibernation_swap || + !bdev_nonrot(p->bdev)) atomic_dec(&nr_rotate_swap); mutex_lock(&swapon_mutex); @@ -3001,6 +3007,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; @@ -3076,13 +3083,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 && bdev_stable_writes(p->bdev)) p->flags |= SWP_STABLE_WRITES; if (p->bdev && p->bdev->bd_disk->fops->rw_page) p->flags |= SWP_SYNCHRONOUS_IO; - if (p->bdev && bdev_nonrot(p->bdev)) { + if (p->bdev && !hibernation_swap && + bdev_nonrot(p->bdev)) { int cpu; unsigned long ci, nr_cluster;