linux/arch/s390/kernel/crash_dump.c
<<
>>
Prefs
   1/*
   2 * S390 kdump implementation
   3 *
   4 * Copyright IBM Corp. 2011
   5 * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
   6 */
   7
   8#include <linux/crash_dump.h>
   9#include <asm/lowcore.h>
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/gfp.h>
  13#include <linux/slab.h>
  14#include <linux/bootmem.h>
  15#include <linux/elf.h>
  16#include <asm/asm-offsets.h>
  17#include <linux/memblock.h>
  18#include <asm/os_info.h>
  19#include <asm/elf.h>
  20#include <asm/ipl.h>
  21#include <asm/sclp.h>
  22
  23#define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y)))
  24#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
  25#define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y))))
  26
  27static struct memblock_region oldmem_region;
  28
  29static struct memblock_type oldmem_type = {
  30        .cnt = 1,
  31        .max = 1,
  32        .total_size = 0,
  33        .regions = &oldmem_region,
  34};
  35
  36struct save_area {
  37        struct list_head list;
  38        u64 psw[2];
  39        u64 ctrs[16];
  40        u64 gprs[16];
  41        u32 acrs[16];
  42        u64 fprs[16];
  43        u32 fpc;
  44        u32 prefix;
  45        u64 todpreg;
  46        u64 timer;
  47        u64 todcmp;
  48        u64 vxrs_low[16];
  49        __vector128 vxrs_high[16];
  50};
  51
  52static LIST_HEAD(dump_save_areas);
  53
  54/*
  55 * Allocate a save area
  56 */
  57struct save_area * __init save_area_alloc(bool is_boot_cpu)
  58{
  59        struct save_area *sa;
  60
  61        sa = (void *) memblock_alloc(sizeof(*sa), 8);
  62        if (is_boot_cpu)
  63                list_add(&sa->list, &dump_save_areas);
  64        else
  65                list_add_tail(&sa->list, &dump_save_areas);
  66        return sa;
  67}
  68
  69/*
  70 * Return the address of the save area for the boot CPU
  71 */
  72struct save_area * __init save_area_boot_cpu(void)
  73{
  74        if (list_empty(&dump_save_areas))
  75                return NULL;
  76        return list_first_entry(&dump_save_areas, struct save_area, list);
  77}
  78
  79/*
  80 * Copy CPU registers into the save area
  81 */
  82void __init save_area_add_regs(struct save_area *sa, void *regs)
  83{
  84        struct lowcore *lc;
  85
  86        lc = (struct lowcore *)(regs - __LC_FPREGS_SAVE_AREA);
  87        memcpy(&sa->psw, &lc->psw_save_area, sizeof(sa->psw));
  88        memcpy(&sa->ctrs, &lc->cregs_save_area, sizeof(sa->ctrs));
  89        memcpy(&sa->gprs, &lc->gpregs_save_area, sizeof(sa->gprs));
  90        memcpy(&sa->acrs, &lc->access_regs_save_area, sizeof(sa->acrs));
  91        memcpy(&sa->fprs, &lc->floating_pt_save_area, sizeof(sa->fprs));
  92        memcpy(&sa->fpc, &lc->fpt_creg_save_area, sizeof(sa->fpc));
  93        memcpy(&sa->prefix, &lc->prefixreg_save_area, sizeof(sa->prefix));
  94        memcpy(&sa->todpreg, &lc->tod_progreg_save_area, sizeof(sa->todpreg));
  95        memcpy(&sa->timer, &lc->cpu_timer_save_area, sizeof(sa->timer));
  96        memcpy(&sa->todcmp, &lc->clock_comp_save_area, sizeof(sa->todcmp));
  97}
  98
  99/*
 100 * Copy vector registers into the save area
 101 */
 102void __init save_area_add_vxrs(struct save_area *sa, __vector128 *vxrs)
 103{
 104        int i;
 105
 106        /* Copy lower halves of vector registers 0-15 */
 107        for (i = 0; i < 16; i++)
 108                memcpy(&sa->vxrs_low[i], &vxrs[i].u[2], 8);
 109        /* Copy vector registers 16-31 */
 110        memcpy(sa->vxrs_high, vxrs + 16, 16 * sizeof(__vector128));
 111}
 112
 113/*
 114 * Return physical address for virtual address
 115 */
 116static inline void *load_real_addr(void *addr)
 117{
 118        unsigned long real_addr;
 119
 120        asm volatile(
 121                   "    lra     %0,0(%1)\n"
 122                   "    jz      0f\n"
 123                   "    la      %0,0\n"
 124                   "0:"
 125                   : "=a" (real_addr) : "a" (addr) : "cc");
 126        return (void *)real_addr;
 127}
 128
 129/*
 130 * Copy memory of the old, dumped system to a kernel space virtual address
 131 */
 132int copy_oldmem_kernel(void *dst, void *src, size_t count)
 133{
 134        unsigned long from, len;
 135        void *ra;
 136        int rc;
 137
 138        while (count) {
 139                from = __pa(src);
 140                if (!OLDMEM_BASE && from < sclp.hsa_size) {
 141                        /* Copy from zfcpdump HSA area */
 142                        len = min(count, sclp.hsa_size - from);
 143                        rc = memcpy_hsa_kernel(dst, from, len);
 144                        if (rc)
 145                                return rc;
 146                } else {
 147                        /* Check for swapped kdump oldmem areas */
 148                        if (OLDMEM_BASE && from - OLDMEM_BASE < OLDMEM_SIZE) {
 149                                from -= OLDMEM_BASE;
 150                                len = min(count, OLDMEM_SIZE - from);
 151                        } else if (OLDMEM_BASE && from < OLDMEM_SIZE) {
 152                                len = min(count, OLDMEM_SIZE - from);
 153                                from += OLDMEM_BASE;
 154                        } else {
 155                                len = count;
 156                        }
 157                        if (is_vmalloc_or_module_addr(dst)) {
 158                                ra = load_real_addr(dst);
 159                                len = min(PAGE_SIZE - offset_in_page(ra), len);
 160                        } else {
 161                                ra = dst;
 162                        }
 163                        if (memcpy_real(ra, (void *) from, len))
 164                                return -EFAULT;
 165                }
 166                dst += len;
 167                src += len;
 168                count -= len;
 169        }
 170        return 0;
 171}
 172
 173/*
 174 * Copy memory of the old, dumped system to a user space virtual address
 175 */
 176static int copy_oldmem_user(void __user *dst, void *src, size_t count)
 177{
 178        unsigned long from, len;
 179        int rc;
 180
 181        while (count) {
 182                from = __pa(src);
 183                if (!OLDMEM_BASE && from < sclp.hsa_size) {
 184                        /* Copy from zfcpdump HSA area */
 185                        len = min(count, sclp.hsa_size - from);
 186                        rc = memcpy_hsa_user(dst, from, len);
 187                        if (rc)
 188                                return rc;
 189                } else {
 190                        /* Check for swapped kdump oldmem areas */
 191                        if (OLDMEM_BASE && from - OLDMEM_BASE < OLDMEM_SIZE) {
 192                                from -= OLDMEM_BASE;
 193                                len = min(count, OLDMEM_SIZE - from);
 194                        } else if (OLDMEM_BASE && from < OLDMEM_SIZE) {
 195                                len = min(count, OLDMEM_SIZE - from);
 196                                from += OLDMEM_BASE;
 197                        } else {
 198                                len = count;
 199                        }
 200                        rc = copy_to_user_real(dst, (void *) from, count);
 201                        if (rc)
 202                                return rc;
 203                }
 204                dst += len;
 205                src += len;
 206                count -= len;
 207        }
 208        return 0;
 209}
 210
 211/*
 212 * Copy one page from "oldmem"
 213 */
 214ssize_t copy_oldmem_page(unsigned long pfn, char *buf, size_t csize,
 215                         unsigned long offset, int userbuf)
 216{
 217        void *src;
 218        int rc;
 219
 220        if (!csize)
 221                return 0;
 222        src = (void *) (pfn << PAGE_SHIFT) + offset;
 223        if (userbuf)
 224                rc = copy_oldmem_user((void __force __user *) buf, src, csize);
 225        else
 226                rc = copy_oldmem_kernel((void *) buf, src, csize);
 227        return rc;
 228}
 229
 230/*
 231 * Remap "oldmem" for kdump
 232 *
 233 * For the kdump reserved memory this functions performs a swap operation:
 234 * [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE]
 235 */
 236static int remap_oldmem_pfn_range_kdump(struct vm_area_struct *vma,
 237                                        unsigned long from, unsigned long pfn,
 238                                        unsigned long size, pgprot_t prot)
 239{
 240        unsigned long size_old;
 241        int rc;
 242
 243        if (pfn < OLDMEM_SIZE >> PAGE_SHIFT) {
 244                size_old = min(size, OLDMEM_SIZE - (pfn << PAGE_SHIFT));
 245                rc = remap_pfn_range(vma, from,
 246                                     pfn + (OLDMEM_BASE >> PAGE_SHIFT),
 247                                     size_old, prot);
 248                if (rc || size == size_old)
 249                        return rc;
 250                size -= size_old;
 251                from += size_old;
 252                pfn += size_old >> PAGE_SHIFT;
 253        }
 254        return remap_pfn_range(vma, from, pfn, size, prot);
 255}
 256
 257/*
 258 * Remap "oldmem" for zfcpdump
 259 *
 260 * We only map available memory above HSA size. Memory below HSA size
 261 * is read on demand using the copy_oldmem_page() function.
 262 */
 263static int remap_oldmem_pfn_range_zfcpdump(struct vm_area_struct *vma,
 264                                           unsigned long from,
 265                                           unsigned long pfn,
 266                                           unsigned long size, pgprot_t prot)
 267{
 268        unsigned long hsa_end = sclp.hsa_size;
 269        unsigned long size_hsa;
 270
 271        if (pfn < hsa_end >> PAGE_SHIFT) {
 272                size_hsa = min(size, hsa_end - (pfn << PAGE_SHIFT));
 273                if (size == size_hsa)
 274                        return 0;
 275                size -= size_hsa;
 276                from += size_hsa;
 277                pfn += size_hsa >> PAGE_SHIFT;
 278        }
 279        return remap_pfn_range(vma, from, pfn, size, prot);
 280}
 281
 282/*
 283 * Remap "oldmem" for kdump or zfcpdump
 284 */
 285int remap_oldmem_pfn_range(struct vm_area_struct *vma, unsigned long from,
 286                           unsigned long pfn, unsigned long size, pgprot_t prot)
 287{
 288        if (OLDMEM_BASE)
 289                return remap_oldmem_pfn_range_kdump(vma, from, pfn, size, prot);
 290        else
 291                return remap_oldmem_pfn_range_zfcpdump(vma, from, pfn, size,
 292                                                       prot);
 293}
 294
 295/*
 296 * Alloc memory and panic in case of ENOMEM
 297 */
 298static void *kzalloc_panic(int len)
 299{
 300        void *rc;
 301
 302        rc = kzalloc(len, GFP_KERNEL);
 303        if (!rc)
 304                panic("s390 kdump kzalloc (%d) failed", len);
 305        return rc;
 306}
 307
 308/*
 309 * Initialize ELF note
 310 */
 311static void *nt_init_name(void *buf, Elf64_Word type, void *desc, int d_len,
 312                          const char *name)
 313{
 314        Elf64_Nhdr *note;
 315        u64 len;
 316
 317        note = (Elf64_Nhdr *)buf;
 318        note->n_namesz = strlen(name) + 1;
 319        note->n_descsz = d_len;
 320        note->n_type = type;
 321        len = sizeof(Elf64_Nhdr);
 322
 323        memcpy(buf + len, name, note->n_namesz);
 324        len = roundup(len + note->n_namesz, 4);
 325
 326        memcpy(buf + len, desc, note->n_descsz);
 327        len = roundup(len + note->n_descsz, 4);
 328
 329        return PTR_ADD(buf, len);
 330}
 331
 332static inline void *nt_init(void *buf, Elf64_Word type, void *desc, int d_len)
 333{
 334        return nt_init_name(buf, type, desc, d_len, KEXEC_CORE_NOTE_NAME);
 335}
 336
 337/*
 338 * Fill ELF notes for one CPU with save area registers
 339 */
 340static void *fill_cpu_elf_notes(void *ptr, int cpu, struct save_area *sa)
 341{
 342        struct elf_prstatus nt_prstatus;
 343        elf_fpregset_t nt_fpregset;
 344
 345        /* Prepare prstatus note */
 346        memset(&nt_prstatus, 0, sizeof(nt_prstatus));
 347        memcpy(&nt_prstatus.pr_reg.gprs, sa->gprs, sizeof(sa->gprs));
 348        memcpy(&nt_prstatus.pr_reg.psw, sa->psw, sizeof(sa->psw));
 349        memcpy(&nt_prstatus.pr_reg.acrs, sa->acrs, sizeof(sa->acrs));
 350        nt_prstatus.pr_pid = cpu;
 351        /* Prepare fpregset (floating point) note */
 352        memset(&nt_fpregset, 0, sizeof(nt_fpregset));
 353        memcpy(&nt_fpregset.fpc, &sa->fpc, sizeof(sa->fpc));
 354        memcpy(&nt_fpregset.fprs, &sa->fprs, sizeof(sa->fprs));
 355        /* Create ELF notes for the CPU */
 356        ptr = nt_init(ptr, NT_PRSTATUS, &nt_prstatus, sizeof(nt_prstatus));
 357        ptr = nt_init(ptr, NT_PRFPREG, &nt_fpregset, sizeof(nt_fpregset));
 358        ptr = nt_init(ptr, NT_S390_TIMER, &sa->timer, sizeof(sa->timer));
 359        ptr = nt_init(ptr, NT_S390_TODCMP, &sa->todcmp, sizeof(sa->todcmp));
 360        ptr = nt_init(ptr, NT_S390_TODPREG, &sa->todpreg, sizeof(sa->todpreg));
 361        ptr = nt_init(ptr, NT_S390_CTRS, &sa->ctrs, sizeof(sa->ctrs));
 362        ptr = nt_init(ptr, NT_S390_PREFIX, &sa->prefix, sizeof(sa->prefix));
 363        if (MACHINE_HAS_VX) {
 364                ptr = nt_init(ptr, NT_S390_VXRS_HIGH,
 365                              &sa->vxrs_high, sizeof(sa->vxrs_high));
 366                ptr = nt_init(ptr, NT_S390_VXRS_LOW,
 367                              &sa->vxrs_low, sizeof(sa->vxrs_low));
 368        }
 369        return ptr;
 370}
 371
 372/*
 373 * Initialize prpsinfo note (new kernel)
 374 */
 375static void *nt_prpsinfo(void *ptr)
 376{
 377        struct elf_prpsinfo prpsinfo;
 378
 379        memset(&prpsinfo, 0, sizeof(prpsinfo));
 380        prpsinfo.pr_sname = 'R';
 381        strcpy(prpsinfo.pr_fname, "vmlinux");
 382        return nt_init(ptr, NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo));
 383}
 384
 385/*
 386 * Get vmcoreinfo using lowcore->vmcore_info (new kernel)
 387 */
 388static void *get_vmcoreinfo_old(unsigned long *size)
 389{
 390        char nt_name[11], *vmcoreinfo;
 391        Elf64_Nhdr note;
 392        void *addr;
 393
 394        if (copy_oldmem_kernel(&addr, &S390_lowcore.vmcore_info, sizeof(addr)))
 395                return NULL;
 396        memset(nt_name, 0, sizeof(nt_name));
 397        if (copy_oldmem_kernel(&note, addr, sizeof(note)))
 398                return NULL;
 399        if (copy_oldmem_kernel(nt_name, addr + sizeof(note),
 400                               sizeof(nt_name) - 1))
 401                return NULL;
 402        if (strcmp(nt_name, "VMCOREINFO") != 0)
 403                return NULL;
 404        vmcoreinfo = kzalloc_panic(note.n_descsz);
 405        if (copy_oldmem_kernel(vmcoreinfo, addr + 24, note.n_descsz))
 406                return NULL;
 407        *size = note.n_descsz;
 408        return vmcoreinfo;
 409}
 410
 411/*
 412 * Initialize vmcoreinfo note (new kernel)
 413 */
 414static void *nt_vmcoreinfo(void *ptr)
 415{
 416        unsigned long size;
 417        void *vmcoreinfo;
 418
 419        vmcoreinfo = os_info_old_entry(OS_INFO_VMCOREINFO, &size);
 420        if (!vmcoreinfo)
 421                vmcoreinfo = get_vmcoreinfo_old(&size);
 422        if (!vmcoreinfo)
 423                return ptr;
 424        return nt_init_name(ptr, 0, vmcoreinfo, size, "VMCOREINFO");
 425}
 426
 427/*
 428 * Initialize ELF header (new kernel)
 429 */
 430static void *ehdr_init(Elf64_Ehdr *ehdr, int mem_chunk_cnt)
 431{
 432        memset(ehdr, 0, sizeof(*ehdr));
 433        memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
 434        ehdr->e_ident[EI_CLASS] = ELFCLASS64;
 435        ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
 436        ehdr->e_ident[EI_VERSION] = EV_CURRENT;
 437        memset(ehdr->e_ident + EI_PAD, 0, EI_NIDENT - EI_PAD);
 438        ehdr->e_type = ET_CORE;
 439        ehdr->e_machine = EM_S390;
 440        ehdr->e_version = EV_CURRENT;
 441        ehdr->e_phoff = sizeof(Elf64_Ehdr);
 442        ehdr->e_ehsize = sizeof(Elf64_Ehdr);
 443        ehdr->e_phentsize = sizeof(Elf64_Phdr);
 444        ehdr->e_phnum = mem_chunk_cnt + 1;
 445        return ehdr + 1;
 446}
 447
 448/*
 449 * Return CPU count for ELF header (new kernel)
 450 */
 451static int get_cpu_cnt(void)
 452{
 453        struct save_area *sa;
 454        int cpus = 0;
 455
 456        list_for_each_entry(sa, &dump_save_areas, list)
 457                if (sa->prefix != 0)
 458                        cpus++;
 459        return cpus;
 460}
 461
 462/*
 463 * Return memory chunk count for ELF header (new kernel)
 464 */
 465static int get_mem_chunk_cnt(void)
 466{
 467        int cnt = 0;
 468        u64 idx;
 469
 470        for_each_mem_range(idx, &memblock.physmem, &oldmem_type, NUMA_NO_NODE,
 471                           MEMBLOCK_NONE, NULL, NULL, NULL)
 472                cnt++;
 473        return cnt;
 474}
 475
 476/*
 477 * Initialize ELF loads (new kernel)
 478 */
 479static void loads_init(Elf64_Phdr *phdr, u64 loads_offset)
 480{
 481        phys_addr_t start, end;
 482        u64 idx;
 483
 484        for_each_mem_range(idx, &memblock.physmem, &oldmem_type, NUMA_NO_NODE,
 485                           MEMBLOCK_NONE, &start, &end, NULL) {
 486                phdr->p_filesz = end - start;
 487                phdr->p_type = PT_LOAD;
 488                phdr->p_offset = start;
 489                phdr->p_vaddr = start;
 490                phdr->p_paddr = start;
 491                phdr->p_memsz = end - start;
 492                phdr->p_flags = PF_R | PF_W | PF_X;
 493                phdr->p_align = PAGE_SIZE;
 494                phdr++;
 495        }
 496}
 497
 498/*
 499 * Initialize notes (new kernel)
 500 */
 501static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
 502{
 503        struct save_area *sa;
 504        void *ptr_start = ptr;
 505        int cpu;
 506
 507        ptr = nt_prpsinfo(ptr);
 508
 509        cpu = 1;
 510        list_for_each_entry(sa, &dump_save_areas, list)
 511                if (sa->prefix != 0)
 512                        ptr = fill_cpu_elf_notes(ptr, cpu++, sa);
 513        ptr = nt_vmcoreinfo(ptr);
 514        memset(phdr, 0, sizeof(*phdr));
 515        phdr->p_type = PT_NOTE;
 516        phdr->p_offset = notes_offset;
 517        phdr->p_filesz = (unsigned long) PTR_SUB(ptr, ptr_start);
 518        phdr->p_memsz = phdr->p_filesz;
 519        return ptr;
 520}
 521
 522/*
 523 * Create ELF core header (new kernel)
 524 */
 525int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
 526{
 527        Elf64_Phdr *phdr_notes, *phdr_loads;
 528        int mem_chunk_cnt;
 529        void *ptr, *hdr;
 530        u32 alloc_size;
 531        u64 hdr_off;
 532
 533        /* If we are not in kdump or zfcpdump mode return */
 534        if (!OLDMEM_BASE && ipl_info.type != IPL_TYPE_FCP_DUMP)
 535                return 0;
 536        /* If we cannot get HSA size for zfcpdump return error */
 537        if (ipl_info.type == IPL_TYPE_FCP_DUMP && !sclp.hsa_size)
 538                return -ENODEV;
 539
 540        /* For kdump, exclude previous crashkernel memory */
 541        if (OLDMEM_BASE) {
 542                oldmem_region.base = OLDMEM_BASE;
 543                oldmem_region.size = OLDMEM_SIZE;
 544                oldmem_type.total_size = OLDMEM_SIZE;
 545        }
 546
 547        mem_chunk_cnt = get_mem_chunk_cnt();
 548
 549        alloc_size = 0x1000 + get_cpu_cnt() * 0x4a0 +
 550                mem_chunk_cnt * sizeof(Elf64_Phdr);
 551        hdr = kzalloc_panic(alloc_size);
 552        /* Init elf header */
 553        ptr = ehdr_init(hdr, mem_chunk_cnt);
 554        /* Init program headers */
 555        phdr_notes = ptr;
 556        ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr));
 557        phdr_loads = ptr;
 558        ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr) * mem_chunk_cnt);
 559        /* Init notes */
 560        hdr_off = PTR_DIFF(ptr, hdr);
 561        ptr = notes_init(phdr_notes, ptr, ((unsigned long) hdr) + hdr_off);
 562        /* Init loads */
 563        hdr_off = PTR_DIFF(ptr, hdr);
 564        loads_init(phdr_loads, hdr_off);
 565        *addr = (unsigned long long) hdr;
 566        *size = (unsigned long long) hdr_off;
 567        BUG_ON(elfcorehdr_size > alloc_size);
 568        return 0;
 569}
 570
 571/*
 572 * Free ELF core header (new kernel)
 573 */
 574void elfcorehdr_free(unsigned long long addr)
 575{
 576        kfree((void *)(unsigned long)addr);
 577}
 578
 579/*
 580 * Read from ELF header
 581 */
 582ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos)
 583{
 584        void *src = (void *)(unsigned long)*ppos;
 585
 586        memcpy(buf, src, count);
 587        *ppos += count;
 588        return count;
 589}
 590
 591/*
 592 * Read from ELF notes data
 593 */
 594ssize_t elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos)
 595{
 596        void *src = (void *)(unsigned long)*ppos;
 597
 598        memcpy(buf, src, count);
 599        *ppos += count;
 600        return count;
 601}
 602