0001
0002 #include <linux/init.h>
0003 #include <linux/memblock.h>
0004 #include <linux/fs.h>
0005 #include <linux/sysfs.h>
0006 #include <linux/kobject.h>
0007 #include <linux/memory_hotplug.h>
0008 #include <linux/mm.h>
0009 #include <linux/mmzone.h>
0010 #include <linux/pagemap.h>
0011 #include <linux/rmap.h>
0012 #include <linux/mmu_notifier.h>
0013 #include <linux/page_ext.h>
0014 #include <linux/page_idle.h>
0015
0016 #include "internal.h"
0017
0018 #define BITMAP_CHUNK_SIZE sizeof(u64)
0019 #define BITMAP_CHUNK_BITS (BITMAP_CHUNK_SIZE * BITS_PER_BYTE)
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 static struct page *page_idle_get_page(unsigned long pfn)
0035 {
0036 struct page *page = pfn_to_online_page(pfn);
0037
0038 if (!page || !PageLRU(page) ||
0039 !get_page_unless_zero(page))
0040 return NULL;
0041
0042 if (unlikely(!PageLRU(page))) {
0043 put_page(page);
0044 page = NULL;
0045 }
0046 return page;
0047 }
0048
0049 static bool page_idle_clear_pte_refs_one(struct folio *folio,
0050 struct vm_area_struct *vma,
0051 unsigned long addr, void *arg)
0052 {
0053 DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, addr, 0);
0054 bool referenced = false;
0055
0056 while (page_vma_mapped_walk(&pvmw)) {
0057 addr = pvmw.address;
0058 if (pvmw.pte) {
0059
0060
0061
0062
0063 if (ptep_clear_young_notify(vma, addr, pvmw.pte))
0064 referenced = true;
0065 } else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
0066 if (pmdp_clear_young_notify(vma, addr, pvmw.pmd))
0067 referenced = true;
0068 } else {
0069
0070 WARN_ON_ONCE(1);
0071 }
0072 }
0073
0074 if (referenced) {
0075 folio_clear_idle(folio);
0076
0077
0078
0079
0080
0081 folio_set_young(folio);
0082 }
0083 return true;
0084 }
0085
0086 static void page_idle_clear_pte_refs(struct page *page)
0087 {
0088 struct folio *folio = page_folio(page);
0089
0090
0091
0092
0093
0094 static struct rmap_walk_control rwc = {
0095 .rmap_one = page_idle_clear_pte_refs_one,
0096 .anon_lock = folio_lock_anon_vma_read,
0097 };
0098 bool need_lock;
0099
0100 if (!folio_mapped(folio) || !folio_raw_mapping(folio))
0101 return;
0102
0103 need_lock = !folio_test_anon(folio) || folio_test_ksm(folio);
0104 if (need_lock && !folio_trylock(folio))
0105 return;
0106
0107 rmap_walk(folio, &rwc);
0108
0109 if (need_lock)
0110 folio_unlock(folio);
0111 }
0112
0113 static ssize_t page_idle_bitmap_read(struct file *file, struct kobject *kobj,
0114 struct bin_attribute *attr, char *buf,
0115 loff_t pos, size_t count)
0116 {
0117 u64 *out = (u64 *)buf;
0118 struct page *page;
0119 unsigned long pfn, end_pfn;
0120 int bit;
0121
0122 if (pos % BITMAP_CHUNK_SIZE || count % BITMAP_CHUNK_SIZE)
0123 return -EINVAL;
0124
0125 pfn = pos * BITS_PER_BYTE;
0126 if (pfn >= max_pfn)
0127 return 0;
0128
0129 end_pfn = pfn + count * BITS_PER_BYTE;
0130 if (end_pfn > max_pfn)
0131 end_pfn = max_pfn;
0132
0133 for (; pfn < end_pfn; pfn++) {
0134 bit = pfn % BITMAP_CHUNK_BITS;
0135 if (!bit)
0136 *out = 0ULL;
0137 page = page_idle_get_page(pfn);
0138 if (page) {
0139 if (page_is_idle(page)) {
0140
0141
0142
0143
0144
0145 page_idle_clear_pte_refs(page);
0146 if (page_is_idle(page))
0147 *out |= 1ULL << bit;
0148 }
0149 put_page(page);
0150 }
0151 if (bit == BITMAP_CHUNK_BITS - 1)
0152 out++;
0153 cond_resched();
0154 }
0155 return (char *)out - buf;
0156 }
0157
0158 static ssize_t page_idle_bitmap_write(struct file *file, struct kobject *kobj,
0159 struct bin_attribute *attr, char *buf,
0160 loff_t pos, size_t count)
0161 {
0162 const u64 *in = (u64 *)buf;
0163 struct page *page;
0164 unsigned long pfn, end_pfn;
0165 int bit;
0166
0167 if (pos % BITMAP_CHUNK_SIZE || count % BITMAP_CHUNK_SIZE)
0168 return -EINVAL;
0169
0170 pfn = pos * BITS_PER_BYTE;
0171 if (pfn >= max_pfn)
0172 return -ENXIO;
0173
0174 end_pfn = pfn + count * BITS_PER_BYTE;
0175 if (end_pfn > max_pfn)
0176 end_pfn = max_pfn;
0177
0178 for (; pfn < end_pfn; pfn++) {
0179 bit = pfn % BITMAP_CHUNK_BITS;
0180 if ((*in >> bit) & 1) {
0181 page = page_idle_get_page(pfn);
0182 if (page) {
0183 page_idle_clear_pte_refs(page);
0184 set_page_idle(page);
0185 put_page(page);
0186 }
0187 }
0188 if (bit == BITMAP_CHUNK_BITS - 1)
0189 in++;
0190 cond_resched();
0191 }
0192 return (char *)in - buf;
0193 }
0194
0195 static struct bin_attribute page_idle_bitmap_attr =
0196 __BIN_ATTR(bitmap, 0600,
0197 page_idle_bitmap_read, page_idle_bitmap_write, 0);
0198
0199 static struct bin_attribute *page_idle_bin_attrs[] = {
0200 &page_idle_bitmap_attr,
0201 NULL,
0202 };
0203
0204 static const struct attribute_group page_idle_attr_group = {
0205 .bin_attrs = page_idle_bin_attrs,
0206 .name = "page_idle",
0207 };
0208
0209 static int __init page_idle_init(void)
0210 {
0211 int err;
0212
0213 err = sysfs_create_group(mm_kobj, &page_idle_attr_group);
0214 if (err) {
0215 pr_err("page_idle: register sysfs failed\n");
0216 return err;
0217 }
0218 return 0;
0219 }
0220 subsys_initcall(page_idle_init);