powerpc/mm: Flush cache on memory hot(un)plug
RFC 1/2 powerpc/mm: Flush cache on memory hot(un)plug
This patch adds support for flushing potentially dirty cache lines when memory is hot-plugged/hot-un-plugged. The support is currently limited to 64 bit systems.
The bug was exposed when mappings for a coherent memory device were actually hot-unplugged and plugged in back later. A similar issue was observed during the development of memtrace, but memtrace does it's own flushing of region via a custom routine.
These patches do a flush both on hotplug/unplug to clear any stale data in the cache w.r.t mappings, there is a small race window where a clean cache line may be created again just prior to tearing down the mapping. Flushing them on establishment of new mappings helps start with a clean state.
The patches were tested by disabling the flush routines in memtrace and doing I/O on the trace file. The system immediately checkstops (quite reliably, if prior to the hot-unplug of the memtrace region, we memset the regions we are about to hot unplug). After these patches no custom flushing is needed in the memtrace code.
--- arch/powerpc/mm/mem.c | 2 ++ 1 file changed, 2 insertions(+)
arch/powerpc/mm/mem.c +2 -0
@@ -143,6 +143,7 @@ int __meminit arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap * start, start + size, rc);return -EFAULT ; } +flush_inval_dcache_range (start, start + size);return __add_pages (nid, start_pfn, nr_pages, altmap, want_memblock); }
@@ -169,6 +170,7 @@ int __meminit arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap/* Remove htab bolted mappings for this section of memory */ start = (unsigned long )__va (start); +flush_inval_dcache_range (start, start + size); ret =remove_section_mapping (start, start + size);/* Ensure all vmalloc mappings are flushed in case they also
Signature · 1 line
2.13.6
RFC 2/2 powerpc/mm/memtrace: Let the arch hotunplug code flush cache
Don't do this via custom code, instead now that we have support in the arch hotplug/hotunplug code, rely on those routines to do the right thing.
--- arch/powerpc/platforms/powernv/memtrace.c | 17 ----------------- 1 file changed, 17 deletions(-)
arch/powerpc/platforms/powernv/memtrace.c +0 -17
@@ -82,19 +82,6 @@ static const struct file_operations memtrace_fops = { .open = simple_open, }; -static void flush_memory_region (u64 base,u64 size) -{ -unsigned long line_size = ppc64_caches.l1d.size; -u64 end = base + size; -u64 addr; - - base =round_down (base, line_size); - end =round_up (end, line_size); - -for (addr = base; addr < end; addr += line_size) - asmvolatile ("dcbf 0,%0" :"=r" (addr) ::"memory" ); -} -static int check_memblock_online (struct memory_block *mem,void *arg) {if (mem->state !=MEM_ONLINE )
@@ -132,10 +119,6 @@ static bool memtrace_offline_pages(u32 nid, u64 start_pfn, u64 nr_pages)walk_memory_range (start_pfn, end_pfn, (void *)MEM_OFFLINE , change_memblock_state); -/* RCU grace period? */ -flush_memory_region ((u64 )__va (start_pfn <<PAGE_SHIFT ), - nr_pages <<PAGE_SHIFT ); -lock_device_hotplug ();remove_memory (nid, start_pfn <<PAGE_SHIFT , nr_pages <<PAGE_SHIFT );unlock_device_hotplug ();
Signature · 1 line
2.13.6