• Eugene Surovegin's avatar
    percpu: fix per_cpu_ptr_to_phys() handling of non-page-aligned addresses · 9f57bd4d
    Eugene Surovegin authored
    per_cpu_ptr_to_phys() incorrectly rounds up its result for non-kmalloc
    case to the page boundary, which is bogus for any non-page-aligned
    address.
    
    This affects the only in-tree user of this function - sysfs handler
    for per-cpu 'crash_notes' physical address.  The trouble is that the
    crash_notes per-cpu variable is not page-aligned:
    
    crash_notes = 0xc08e8ed4
    PER-CPU OFFSET VALUES:
     CPU 0: 3711f000
     CPU 1: 37129000
     CPU 2: 37133000
     CPU 3: 3713d000
    
    So, the per-cpu addresses are:
     crash_notes on CPU 0: f7a07ed4 => phys 36b57ed4
     crash_notes on CPU 1: f7a11ed4 => phys 36b4ded4
     crash_notes on CPU 2: f7a1bed4 => phys 36b43ed4
     crash_notes on CPU 3: f7a25ed4 => phys 36b39ed4
    
    However, /sys/devices/system/cpu/cpu*/crash_notes says:
     /sys/devices/system/cpu/cpu0/crash_notes: 36b57000
     /sys/devices/system/cpu/cpu1/crash_notes: 36b4d000
     /sys/devices/system/cpu/cpu2/crash_notes: 36b43000
     /sys/devices/system/cpu/cpu3/crash_notes: 36b39000
    
    As you can see, all values are rounded down to a page
    boundary. Consequently, this is where kexec sets up the NOTE segments,
    and thus where the secondary kernel is looking for them. However, when
    the first kernel crashes, it saves the notes to the unaligned
    addresses, where they are not found.
    
    Fix it by adding offset_in_page() to the translated page address.
    
    -tj: Combined Eugene's and Petr's commit messages.
    Signed-off-by: default avatarEugene Surovegin <ebs@ebshome.net>
    Signed-off-by: default avatarTejun Heo <tj@kernel.org>
    Reported-by: default avatarPetr Tesarik <ptesarik@suse.cz>
    Cc: stable@kernel.org
    9f57bd4d
percpu.c 56.3 KB