Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc: Add kdump support to Collaborative Memory Manager

When running Active Memory Sharing, the Collaborative Memory Manager (CMM)
may mark some pages as "loaned" with the hypervisor. Periodically, the
CMM will query the hypervisor for a loan request, which is a single signed
value. When kexec'ing into a kdump kernel, the CMM driver in the kdump
kernel is not aware of the pages the previous kernel had marked as "loaned",
so the hypervisor and the CMM driver are out of sync. Fix the CMM driver
to handle this scenario by ignoring requests to decrease the number of loaned
pages if we don't think we have any pages loaned. Pages that are marked as
"loaned" which are not in the balloon will automatically get switched to "active"
the next time we touch the page. This also fixes the case where totalram_pages
is smaller than min_mem_mb, which can occur during kdump.

Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

authored by

Brian King and committed by
Benjamin Herrenschmidt
8be8cf5b 6cff46f4

+20 -11
+1 -1
arch/powerpc/platforms/pseries/Kconfig
··· 60 60 61 61 config CMM 62 62 tristate "Collaborative memory management" 63 - depends on PPC_SMLPAR && !CRASH_DUMP 63 + depends on PPC_SMLPAR 64 64 default y 65 65 help 66 66 Select this option, if you want to enable the kernel interface
+19 -10
arch/powerpc/platforms/pseries/cmm.c
··· 229 229 { 230 230 int rc; 231 231 struct hvcall_mpp_data mpp_data; 232 - unsigned long active_pages_target; 233 - signed long page_loan_request; 232 + signed long active_pages_target, page_loan_request, target; 233 + signed long total_pages = totalram_pages + loaned_pages; 234 + signed long min_mem_pages = (min_mem_mb * 1024 * 1024) / PAGE_SIZE; 234 235 235 236 rc = h_get_mpp(&mpp_data); 236 237 ··· 239 238 return; 240 239 241 240 page_loan_request = div_s64((s64)mpp_data.loan_request, PAGE_SIZE); 242 - loaned_pages_target = page_loan_request + loaned_pages; 243 - if (loaned_pages_target > oom_freed_pages) 244 - loaned_pages_target -= oom_freed_pages; 241 + target = page_loan_request + (signed long)loaned_pages; 242 + 243 + if (target < 0 || total_pages < min_mem_pages) 244 + target = 0; 245 + 246 + if (target > oom_freed_pages) 247 + target -= oom_freed_pages; 245 248 else 246 - loaned_pages_target = 0; 249 + target = 0; 247 250 248 - active_pages_target = totalram_pages + loaned_pages - loaned_pages_target; 251 + active_pages_target = total_pages - target; 249 252 250 - if ((min_mem_mb * 1024 * 1024) > (active_pages_target * PAGE_SIZE)) 251 - loaned_pages_target = totalram_pages + loaned_pages - 252 - ((min_mem_mb * 1024 * 1024) / PAGE_SIZE); 253 + if (min_mem_pages > active_pages_target) 254 + target = total_pages - min_mem_pages; 255 + 256 + if (target < 0) 257 + target = 0; 258 + 259 + loaned_pages_target = target; 253 260 254 261 cmm_dbg("delta = %ld, loaned = %lu, target = %lu, oom = %lu, totalram = %lu\n", 255 262 page_loan_request, loaned_pages, loaned_pages_target,