Commit b2fc97c1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull memblock updates from Mike Rapoport:

 - 'reserve_mem' command line parameter to allow creation of named
   memory reservation at boot time.

   The driving use-case is to improve the ability of pstore to retain
   ramoops data across reboots.

 - cleanups and small improvements in memblock and mm_init

 - new tests cases in memblock test suite

* tag 'memblock-v6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock:
  memblock tests: fix implicit declaration of function 'numa_valid_node'
  memblock: Move late alloc warning down to phys alloc
  pstore/ramoops: Add ramoops.mem_name= command line option
  mm/memblock: Add "reserve_mem" to reserved named memory at boot up
  mm/mm_init.c: don't initialize page->lru again
  mm/mm_init.c: not always search next deferred_init_pfn from very beginning
  mm/mm_init.c: use deferred_init_mem_pfn_range_in_zone() to decide loop condition
  mm/mm_init.c: get the highest zone directly
  mm/mm_init.c: move nr_initialised reset down a bit
  mm/memblock: fix a typo in description of for_each_mem_region()
  mm/mm_init.c: use memblock_region_memory_base_pfn() to get startpfn
  mm/memblock: use PAGE_ALIGN_DOWN to get pgend in free_memmap
  mm/memblock: return true directly on finding overlap region
  memblock tests: add memblock_overlaps_region_checks
  mm/memblock: fix comment for memblock_isolate_range()
  memblock tests: add memblock_reserve_many_may_conflict_check()
  memblock tests: add memblock_reserve_all_locations_check()
  mm/memblock: remove empty dummy entry
parents 68b59730 9364a7e4
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -5674,6 +5674,28 @@
			them.  If <base> is less than 0x10000, the region
			is assumed to be I/O ports; otherwise it is memory.

	reserve_mem=	[RAM]
			Format: nn[KNG]:<align>:<label>
			Reserve physical memory and label it with a name that
			other subsystems can use to access it. This is typically
			used for systems that do not wipe the RAM, and this command
			line will try to reserve the same physical memory on
			soft reboots. Note, it is not guaranteed to be the same
			location. For example, if anything about the system changes
			or if booting a different kernel. It can also fail if KASLR
			places the kernel at the location of where the RAM reservation
			was from a previous boot, the new reservation will be at a
			different location.
			Any subsystem using this feature must add a way to verify
			that the contents of the physical memory is from a previous
			boot, as there may be cases where the memory will not be
			located at the same location.

			The format is size:align:label for example, to request
			12 megabytes of 4096 alignment for ramoops:

			reserve_mem=12M:4096:oops ramoops.mem_name=oops

	reservetop=	[X86-32,EARLY]
			Format: nn[KMG]
			Reserves a hole at the top of the kernel virtual
+13 −0
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ and type of the memory area are set using three variables:
  * ``mem_size`` for the size. The memory size will be rounded down to a
    power of two.
  * ``mem_type`` to specify if the memory type (default is pgprot_writecombine).
  * ``mem_name`` to specify a memory region defined by ``reserve_mem`` command
    line parameter.

Typically the default value of ``mem_type=0`` should be used as that sets the pstore
mapping to pgprot_writecombine. Setting ``mem_type=1`` attempts to use
@@ -118,6 +120,17 @@ Setting the ramoops parameters can be done in several different manners:
	return ret;
  }

 D. Using a region of memory reserved via ``reserve_mem`` command line
    parameter. The address and size will be defined by the ``reserve_mem``
    parameter. Note, that ``reserve_mem`` may not always allocate memory
    in the same location, and cannot be relied upon. Testing will need
    to be done, and it may not work on every machine, nor every kernel.
    Consider this a "best effort" approach. The ``reserve_mem`` option
    takes a size, alignment and name as arguments. The name is used
    to map the memory to a label that can be retrieved by ramoops.

	reserver_mem=2M:4096:oops  ramoops.mem_name=oops

You can specify either RAM memory or peripheral devices' memory. However, when
specifying RAM, be sure to reserve the memory by issuing memblock_reserve()
very early in the architecture code, e.g.::
+14 −0
Original line number Diff line number Diff line
@@ -50,6 +50,10 @@ module_param_hw(mem_address, ullong, other, 0400);
MODULE_PARM_DESC(mem_address,
		"start of reserved RAM used to store oops/panic logs");

static char *mem_name;
module_param_named(mem_name, mem_name, charp, 0400);
MODULE_PARM_DESC(mem_name, "name of kernel param that holds addr");

static ulong mem_size;
module_param(mem_size, ulong, 0400);
MODULE_PARM_DESC(mem_size,
@@ -914,6 +918,16 @@ static void __init ramoops_register_dummy(void)
{
	struct ramoops_platform_data pdata;

	if (mem_name) {
		phys_addr_t start;
		phys_addr_t size;

		if (reserve_mem_find_by_name(mem_name, &start, &size)) {
			mem_address = start;
			mem_size = size;
		}
	}

	/*
	 * Prepare a dummy platform data structure to carry the module
	 * parameters. If mem_size isn't set, then there are no module
+1 −20
Original line number Diff line number Diff line
@@ -299,25 +299,6 @@ void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
void __next_mem_pfn_range_in_zone(u64 *idx, struct zone *zone,
				  unsigned long *out_spfn,
				  unsigned long *out_epfn);
/**
 * for_each_free_mem_pfn_range_in_zone - iterate through zone specific free
 * memblock areas
 * @i: u64 used as loop variable
 * @zone: zone in which all of the memory blocks reside
 * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
 * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
 *
 * Walks over free (memory && !reserved) areas of memblock in a specific
 * zone. Available once memblock and an empty zone is initialized. The main
 * assumption is that the zone start, end, and pgdat have been associated.
 * This way we can use the zone to determine NUMA node, and if a given part
 * of the memblock is valid for the zone.
 */
#define for_each_free_mem_pfn_range_in_zone(i, zone, p_start, p_end)	\
	for (i = 0,							\
	     __next_mem_pfn_range_in_zone(&i, zone, p_start, p_end);	\
	     i != U64_MAX;					\
	     __next_mem_pfn_range_in_zone(&i, zone, p_start, p_end))

/**
 * for_each_free_mem_pfn_range_in_zone_from - iterate through zone specific
@@ -565,7 +546,7 @@ static inline unsigned long memblock_region_reserved_end_pfn(const struct memblo
}

/**
 * for_each_mem_region - itereate over memory regions
 * for_each_mem_region - iterate over memory regions
 * @region: loop variable
 */
#define for_each_mem_region(region)					\
+2 −0
Original line number Diff line number Diff line
@@ -4261,4 +4261,6 @@ static inline bool pfn_is_unaccepted_memory(unsigned long pfn)
void vma_pgtable_walk_begin(struct vm_area_struct *vma);
void vma_pgtable_walk_end(struct vm_area_struct *vma);

int reserve_mem_find_by_name(const char *name, phys_addr_t *start, phys_addr_t *size);

#endif /* _LINUX_MM_H */
Loading