^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/mm/mmzone.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * management codes for pgdats, zones and page flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/stddef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/mmzone.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <trace/hooks/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct pglist_data *first_online_pgdat(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) return NODE_DATA(first_online_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct pglist_data *next_online_pgdat(struct pglist_data *pgdat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) int nid = next_online_node(pgdat->node_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) if (nid == MAX_NUMNODES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return NODE_DATA(nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * next_zone - helper magic for for_each_zone()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct zone *next_zone(struct zone *zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) pg_data_t *pgdat = zone->zone_pgdat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) if (zone < pgdat->node_zones + MAX_NR_ZONES - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) zone++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) pgdat = next_online_pgdat(pgdat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (pgdat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) zone = pgdat->node_zones;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) zone = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static inline int zref_in_nodemask(struct zoneref *zref, nodemask_t *nodes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #ifdef CONFIG_NUMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return node_isset(zonelist_node_idx(zref), *nodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #endif /* CONFIG_NUMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* Returns the next zone at or below highest_zoneidx in a zonelist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct zoneref *__next_zones_zonelist(struct zoneref *z,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) enum zone_type highest_zoneidx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) nodemask_t *nodes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * Find the next suitable zone to use for the allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * Only filter based on nodemask if it's set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (unlikely(nodes == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) while (zonelist_zone_idx(z) > highest_zoneidx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) z++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) while (zonelist_zone_idx(z) > highest_zoneidx ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) (z->zone && !zref_in_nodemask(z, nodes)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) z++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) EXPORT_SYMBOL_GPL(__next_zones_zonelist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #ifdef CONFIG_ARCH_HAS_HOLES_MEMORYMODEL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) bool memmap_valid_within(unsigned long pfn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct page *page, struct zone *zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (page_to_pfn(page) != pfn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (page_zone(page) != zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #endif /* CONFIG_ARCH_HAS_HOLES_MEMORYMODEL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) void lruvec_init(struct lruvec *lruvec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) enum lru_list lru;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) memset(lruvec, 0, sizeof(struct lruvec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) for_each_lru(lru)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) INIT_LIST_HEAD(&lruvec->lists[lru]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #if defined(CONFIG_NUMA_BALANCING) && !defined(LAST_CPUPID_NOT_IN_PAGE_FLAGS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int page_cpupid_xchg_last(struct page *page, int cpupid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) unsigned long old_flags, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) int last_cpupid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) old_flags = flags = page->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) last_cpupid = page_cpupid_last(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) flags &= ~(LAST_CPUPID_MASK << LAST_CPUPID_PGSHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) flags |= (cpupid & LAST_CPUPID_MASK) << LAST_CPUPID_PGSHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) } while (unlikely(cmpxchg(&page->flags, old_flags, flags) != old_flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return last_cpupid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) enum zone_type gfp_zone(gfp_t flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) enum zone_type z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) gfp_t local_flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) trace_android_rvh_set_gfp_zone_flags(&local_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) bit = (__force int) ((local_flags) & GFP_ZONEMASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) z = (GFP_ZONE_TABLE >> (bit * GFP_ZONES_SHIFT)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) ((1 << GFP_ZONES_SHIFT) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) VM_BUG_ON((GFP_ZONE_BAD >> bit) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) EXPORT_SYMBOL_GPL(gfp_zone);