14d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt/* 24d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt * crash_dump.c - Memory preserving reboot related code. 34d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt * 44d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt * Created by: Hariprasad Nellitheertha (hari@in.ibm.com) 54d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt * Copyright (C) IBM Corporation, 2004. All rights reserved 64d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt */ 74d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt#include <linux/errno.h> 84d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt#include <linux/crash_dump.h> 94d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt#include <linux/io.h> 104d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt#include <asm/uaccess.h> 114d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt 124d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt/** 134d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt * copy_oldmem_page - copy one page from "oldmem" 144d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt * @pfn: page frame number to be copied 154d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt * @buf: target memory address for the copy; this can be in kernel address 164d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt * space or user address space (see @userbuf) 174d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt * @csize: number of bytes to copy 184d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt * @offset: offset in bytes into the page (based on pfn) to begin the copy 194d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt * @userbuf: if set, @buf is in user address space, use copy_to_user(), 204d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt * otherwise @buf is in kernel address space, use memcpy(). 214d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt * 224d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt * Copy a page from "oldmem". For this page, there is no pte mapped 234d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt * in the current kernel. We stitch up a pte, similar to kmap_atomic. 244d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt */ 254d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundtssize_t copy_oldmem_page(unsigned long pfn, char *buf, 264d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt size_t csize, unsigned long offset, int userbuf) 274d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt{ 284d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt void *vaddr; 294d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt 304d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt if (!csize) 314d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt return 0; 324d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt 334d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE); 344d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt 354d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt if (userbuf) { 364d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt if (copy_to_user(buf, (vaddr + offset), csize)) { 374d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt iounmap(vaddr); 384d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt return -EFAULT; 394d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt } 404d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt } else 414d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt memcpy(buf, (vaddr + offset), csize); 424d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt 434d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt iounmap(vaddr); 444d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt return csize; 454d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt} 46