cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mm_init.c (5389B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * mm_init.c - Memory initialisation verification and debugging
      4 *
      5 * Copyright 2008 IBM Corporation, 2008
      6 * Author Mel Gorman <mel@csn.ul.ie>
      7 *
      8 */
      9#include <linux/kernel.h>
     10#include <linux/init.h>
     11#include <linux/kobject.h>
     12#include <linux/export.h>
     13#include <linux/memory.h>
     14#include <linux/notifier.h>
     15#include <linux/sched.h>
     16#include <linux/mman.h>
     17#include "internal.h"
     18
     19#ifdef CONFIG_DEBUG_MEMORY_INIT
     20int __meminitdata mminit_loglevel;
     21
     22/* The zonelists are simply reported, validation is manual. */
     23void __init mminit_verify_zonelist(void)
     24{
     25	int nid;
     26
     27	if (mminit_loglevel < MMINIT_VERIFY)
     28		return;
     29
     30	for_each_online_node(nid) {
     31		pg_data_t *pgdat = NODE_DATA(nid);
     32		struct zone *zone;
     33		struct zoneref *z;
     34		struct zonelist *zonelist;
     35		int i, listid, zoneid;
     36
     37		BUILD_BUG_ON(MAX_ZONELISTS > 2);
     38		for (i = 0; i < MAX_ZONELISTS * MAX_NR_ZONES; i++) {
     39
     40			/* Identify the zone and nodelist */
     41			zoneid = i % MAX_NR_ZONES;
     42			listid = i / MAX_NR_ZONES;
     43			zonelist = &pgdat->node_zonelists[listid];
     44			zone = &pgdat->node_zones[zoneid];
     45			if (!populated_zone(zone))
     46				continue;
     47
     48			/* Print information about the zonelist */
     49			printk(KERN_DEBUG "mminit::zonelist %s %d:%s = ",
     50				listid > 0 ? "thisnode" : "general", nid,
     51				zone->name);
     52
     53			/* Iterate the zonelist */
     54			for_each_zone_zonelist(zone, z, zonelist, zoneid)
     55				pr_cont("%d:%s ", zone_to_nid(zone), zone->name);
     56			pr_cont("\n");
     57		}
     58	}
     59}
     60
     61void __init mminit_verify_pageflags_layout(void)
     62{
     63	int shift, width;
     64	unsigned long or_mask, add_mask;
     65
     66	shift = 8 * sizeof(unsigned long);
     67	width = shift - SECTIONS_WIDTH - NODES_WIDTH - ZONES_WIDTH
     68		- LAST_CPUPID_SHIFT - KASAN_TAG_WIDTH;
     69	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_widths",
     70		"Section %d Node %d Zone %d Lastcpupid %d Kasantag %d Flags %d\n",
     71		SECTIONS_WIDTH,
     72		NODES_WIDTH,
     73		ZONES_WIDTH,
     74		LAST_CPUPID_WIDTH,
     75		KASAN_TAG_WIDTH,
     76		NR_PAGEFLAGS);
     77	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_shifts",
     78		"Section %d Node %d Zone %d Lastcpupid %d Kasantag %d\n",
     79		SECTIONS_SHIFT,
     80		NODES_SHIFT,
     81		ZONES_SHIFT,
     82		LAST_CPUPID_SHIFT,
     83		KASAN_TAG_WIDTH);
     84	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_pgshifts",
     85		"Section %lu Node %lu Zone %lu Lastcpupid %lu Kasantag %lu\n",
     86		(unsigned long)SECTIONS_PGSHIFT,
     87		(unsigned long)NODES_PGSHIFT,
     88		(unsigned long)ZONES_PGSHIFT,
     89		(unsigned long)LAST_CPUPID_PGSHIFT,
     90		(unsigned long)KASAN_TAG_PGSHIFT);
     91	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_nodezoneid",
     92		"Node/Zone ID: %lu -> %lu\n",
     93		(unsigned long)(ZONEID_PGOFF + ZONEID_SHIFT),
     94		(unsigned long)ZONEID_PGOFF);
     95	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_usage",
     96		"location: %d -> %d layout %d -> %d unused %d -> %d page-flags\n",
     97		shift, width, width, NR_PAGEFLAGS, NR_PAGEFLAGS, 0);
     98#ifdef NODE_NOT_IN_PAGE_FLAGS
     99	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_nodeflags",
    100		"Node not in page flags");
    101#endif
    102#ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS
    103	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_nodeflags",
    104		"Last cpupid not in page flags");
    105#endif
    106
    107	if (SECTIONS_WIDTH) {
    108		shift -= SECTIONS_WIDTH;
    109		BUG_ON(shift != SECTIONS_PGSHIFT);
    110	}
    111	if (NODES_WIDTH) {
    112		shift -= NODES_WIDTH;
    113		BUG_ON(shift != NODES_PGSHIFT);
    114	}
    115	if (ZONES_WIDTH) {
    116		shift -= ZONES_WIDTH;
    117		BUG_ON(shift != ZONES_PGSHIFT);
    118	}
    119
    120	/* Check for bitmask overlaps */
    121	or_mask = (ZONES_MASK << ZONES_PGSHIFT) |
    122			(NODES_MASK << NODES_PGSHIFT) |
    123			(SECTIONS_MASK << SECTIONS_PGSHIFT);
    124	add_mask = (ZONES_MASK << ZONES_PGSHIFT) +
    125			(NODES_MASK << NODES_PGSHIFT) +
    126			(SECTIONS_MASK << SECTIONS_PGSHIFT);
    127	BUG_ON(or_mask != add_mask);
    128}
    129
    130static __init int set_mminit_loglevel(char *str)
    131{
    132	get_option(&str, &mminit_loglevel);
    133	return 0;
    134}
    135early_param("mminit_loglevel", set_mminit_loglevel);
    136#endif /* CONFIG_DEBUG_MEMORY_INIT */
    137
    138struct kobject *mm_kobj;
    139EXPORT_SYMBOL_GPL(mm_kobj);
    140
    141#ifdef CONFIG_SMP
    142s32 vm_committed_as_batch = 32;
    143
    144void mm_compute_batch(int overcommit_policy)
    145{
    146	u64 memsized_batch;
    147	s32 nr = num_present_cpus();
    148	s32 batch = max_t(s32, nr*2, 32);
    149	unsigned long ram_pages = totalram_pages();
    150
    151	/*
    152	 * For policy OVERCOMMIT_NEVER, set batch size to 0.4% of
    153	 * (total memory/#cpus), and lift it to 25% for other policies
    154	 * to easy the possible lock contention for percpu_counter
    155	 * vm_committed_as, while the max limit is INT_MAX
    156	 */
    157	if (overcommit_policy == OVERCOMMIT_NEVER)
    158		memsized_batch = min_t(u64, ram_pages/nr/256, INT_MAX);
    159	else
    160		memsized_batch = min_t(u64, ram_pages/nr/4, INT_MAX);
    161
    162	vm_committed_as_batch = max_t(s32, memsized_batch, batch);
    163}
    164
    165static int __meminit mm_compute_batch_notifier(struct notifier_block *self,
    166					unsigned long action, void *arg)
    167{
    168	switch (action) {
    169	case MEM_ONLINE:
    170	case MEM_OFFLINE:
    171		mm_compute_batch(sysctl_overcommit_memory);
    172		break;
    173	default:
    174		break;
    175	}
    176	return NOTIFY_OK;
    177}
    178
    179static struct notifier_block compute_batch_nb __meminitdata = {
    180	.notifier_call = mm_compute_batch_notifier,
    181	.priority = IPC_CALLBACK_PRI, /* use lowest priority */
    182};
    183
    184static int __init mm_compute_batch_init(void)
    185{
    186	mm_compute_batch(sysctl_overcommit_memory);
    187	register_hotmemory_notifier(&compute_batch_nb);
    188
    189	return 0;
    190}
    191
    192__initcall(mm_compute_batch_init);
    193
    194#endif
    195
    196static int __init mm_sysfs_init(void)
    197{
    198	mm_kobj = kobject_create_and_add("mm", kernel_kobj);
    199	if (!mm_kobj)
    200		return -ENOMEM;
    201
    202	return 0;
    203}
    204postcore_initcall(mm_sysfs_init);