Commit 6c59ddf2 authored by Ma Wupeng's avatar Ma Wupeng Committed by Zheng Zengkai
Browse files

mm: Introduce memory reliable

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4PM01


CVE: NA

--------------------------------

Introduction

============

Memory reliable feature is a memory tiering mechanism. It is based on
kernel mirror feature, which splits memory into two sperate regions,
mirrored(reliable) region and non-mirrored (non-reliable) region.

for kernel mirror feature:

- allocate kernel memory from mirrored region by default
- allocate user memory from non-mirrored region by default

non-mirrored region will be arranged into ZONE_MOVABLE.

for kernel reliable feature, it has additional features below:

- normal user tasks never alloc memory from mirrored region with userspace
  apis(malloc, mmap, etc.)
- special user tasks will allocate memory from mirrored region by default
- tmpfs/pagecache allocate memory from mirrored region by default
- upper limit of mirrored region allcated for user tasks, tmpfs and
  pagecache

Support Reliable fallback mechanism which allows special user tasks, tmpfs
and pagecache can fallback to alloc non-mirrored region, it's the default
setting.

In order to fulfil the goal

- ___GFP_RELIABLE flag added for alloc memory from mirrored region.

- the high_zoneidx for special user tasks/tmpfs/pagecache is set to
  ZONE_NORMAL.

- normal user tasks could only alloc from ZONE_MOVABLE.

This patch is just the main framework, memory reliable support for special
user tasks, pagecache and tmpfs has own patches.

To enable this function, mirrored(reliable) memory is needed and
"kernelcore=reliable" should be added to kernel parameters.

Signed-off-by: default avatarMa Wupeng <mawupeng1@huawei.com>
Reviewed-by: default avatarKefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent 856090e5
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -2227,7 +2227,7 @@
	keepinitrd	[HW,ARM]

	kernelcore=	[KNL,X86,IA-64,PPC,ARM64]
			Format: nn[KMGTPE] | nn% | "mirror"
			Format: nn[KMGTPE] | nn% | "mirror" | "reliable"
			This parameter specifies the amount of memory usable by
			the kernel for non-movable allocations.  The requested
			amount is spread evenly throughout all nodes in the
@@ -2251,6 +2251,9 @@
			for Movable pages.  "nn[KMGTPE]", "nn%", and "mirror"
			are exclusive, so you cannot specify multiple forms.

			Option "reliable" is base on option "mirror", but make
			some extension. These two features are alternatives.

	kgdbdbgp=	[KGDB,HW] kgdb over EHCI usb debug port.
			Format: <Controller#>[,poll interval]
			The controller # is the number of the ehci usb debug
+12 −3
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ struct vm_area_struct;
#define ___GFP_HARDWALL		0x100000u
#define ___GFP_THISNODE		0x200000u
#define ___GFP_ACCOUNT		0x400000u
#define ___GFP_RESERVE_0	0x800000u
#define ___GFP_RELIABLE		0x800000u
#define ___GFP_RESERVE_1	0x1000000u
#ifdef CONFIG_LOCKDEP
#define ___GFP_NOLOCKDEP	0x2000000u
@@ -225,8 +225,10 @@ struct vm_area_struct;
/* Disable lockdep for GFP context tracking */
#define __GFP_NOLOCKDEP ((__force gfp_t)___GFP_NOLOCKDEP)

/* Reserve 2 flags for future usage */
#define __GFP_RESERVE_0 ((__force gfp_t)___GFP_RESERVE_0)
/* Alloc memory from mirrored region */
#define __GFP_RELIABLE ((__force gfp_t)___GFP_RELIABLE)

/* Reserve 1 flags for future usage */
#define __GFP_RESERVE_1 ((__force gfp_t)___GFP_RESERVE_1)

/* Room for N __GFP_FOO bits */
@@ -315,6 +317,7 @@ struct vm_area_struct;
#define GFP_TRANSHUGE_LIGHT	((GFP_HIGHUSER_MOVABLE | __GFP_COMP | \
			 __GFP_NOMEMALLOC | __GFP_NOWARN) & ~__GFP_RECLAIM)
#define GFP_TRANSHUGE	(GFP_TRANSHUGE_LIGHT | __GFP_DIRECT_RECLAIM)
#define GFP_RELIABLE __GFP_RELIABLE

/* Convert GFP flags to their corresponding migrate type */
#define GFP_MOVABLE_MASK (__GFP_RECLAIMABLE|__GFP_MOVABLE)
@@ -461,6 +464,12 @@ static inline enum zone_type gfp_zone(gfp_t flags)
	z = (GFP_ZONE_TABLE >> (bit * GFP_ZONES_SHIFT)) &
					 ((1 << GFP_ZONES_SHIFT) - 1);
	VM_BUG_ON((GFP_ZONE_BAD >> bit) & 1);

#ifdef CONFIG_MEMORY_RELIABLE
	if (z == ZONE_MOVABLE && (flags & GFP_RELIABLE))
		return ZONE_NORMAL;
#endif

	return z;
}

+62 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __MM_MEM_RELIABLE__
#define __MM_MEM_RELIABLE__

#include <linux/stddef.h>
#include <linux/gfp.h>
#include <linux/mmzone.h>
#include <linux/mm_types.h>
#include <linux/sched.h>

#ifdef CONFIG_MEMORY_RELIABLE

extern struct static_key_false mem_reliable;

extern bool reliable_enabled;

extern void add_reliable_mem_size(long sz);
extern void mem_reliable_init(bool has_unmirrored_mem,
			      unsigned long *zone_movable_pfn);

static inline bool mem_reliable_is_enabled(void)
{
	return static_branch_likely(&mem_reliable);
}

static inline bool zone_reliable(struct zone *zone)
{
	return mem_reliable_is_enabled() && zone_idx(zone) < ZONE_MOVABLE;
}

static inline bool skip_none_movable_zone(gfp_t gfp, struct zoneref *z)
{
	if (!mem_reliable_is_enabled())
		return false;

	if (!current->mm || (current->flags & PF_KTHREAD))
		return false;

	/* user tasks can only alloc memory from non-mirrored region */
	if (!(gfp & GFP_RELIABLE) && (gfp & __GFP_HIGHMEM) &&
	    (gfp & __GFP_MOVABLE)) {
		if (zonelist_zone_idx(z) < ZONE_MOVABLE)
			return true;
	}

	return false;
}
#else
#define reliable_enabled 0

static inline bool mem_reliable_is_enabled(void) { return false; }
static inline void add_reliable_mem_size(long sz) {}
static inline void mem_reliable_init(bool has_unmirrored_mem,
				     unsigned long *zone_movable_pfn) {}
static inline bool zone_reliable(struct zone *zone) { return false; }
static inline bool skip_none_movable_zone(gfp_t gfp, struct zoneref *z)
{
	return false;
}
#endif

#endif
+3 −0
Original line number Diff line number Diff line
@@ -34,6 +34,9 @@
#include <linux/pgtable.h>
#include <linux/kabi.h>

/* added to mm.h to avoid every caller adding new header file */
#include <linux/mem_reliable.h>

struct mempolicy;
struct anon_vma;
struct anon_vma_chain;
+1 −1
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@
	{(unsigned long)__GFP_RECLAIM,		"__GFP_RECLAIM"},	\
	{(unsigned long)__GFP_DIRECT_RECLAIM,	"__GFP_DIRECT_RECLAIM"},\
	{(unsigned long)__GFP_KSWAPD_RECLAIM,	"__GFP_KSWAPD_RECLAIM"},\
	{(unsigned long)__GFP_RESERVE_0,	"__GFP_RESERVE_0"},	\
	{(unsigned long)__GFP_RELIABLE,		"__GFP_RELIABLE"},	\
	{(unsigned long)__GFP_RESERVE_1,	"__GFP_RESERVE_1"}	\

#define show_gfp_flags(flags)						\
Loading