diff options
Diffstat (limited to 'makedumpfile.h')
-rw-r--r-- | makedumpfile.h | 2370 |
1 files changed, 2370 insertions, 0 deletions
diff --git a/makedumpfile.h b/makedumpfile.h new file mode 100644 index 0000000..5ff94b8 --- /dev/null +++ b/makedumpfile.h @@ -0,0 +1,2370 @@ +/* + * makedumpfile.h + * + * Copyright (C) 2006, 2007, 2008, 2009, 2011 NEC Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef _MAKEDUMPFILE_H +#define _MAKEDUMPFILE_H + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <gelf.h> +#include <sys/stat.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <time.h> +#include <sys/utsname.h> +#include <sys/wait.h> +#include <zlib.h> +#include <libelf.h> +#include <byteswap.h> +#include <getopt.h> +#include <sys/mman.h> +#ifdef USELZO +#include <lzo/lzo1x.h> +#endif +#ifdef USESNAPPY +#include <snappy-c.h> +#endif +#include "common.h" +#include "dwarf_info.h" +#include "diskdump_mod.h" +#include "print_info.h" +#include "sadump_mod.h" +#include <pthread.h> +#include <semaphore.h> +#include <inttypes.h> + +#define VMEMMAPSTART 0xffffea0000000000UL +#define BITS_PER_WORD 64 + +/* + * Result of command + */ +#define COMPLETED (0) +#define FAILED (1) +#define WRONG_RELEASE (2) /* utsname.release does not match. */ + +/* + * Type of memory management + */ +enum { + NOT_FOUND_MEMTYPE, + SPARSEMEM, + SPARSEMEM_EX, + DISCONTIGMEM, + FLATMEM +}; + +int get_mem_type(void); + +/* + * Page flags + * + * The flag values of page.flags have been defined by enum since linux-2.6.26. + * The following values are for linux-2.6.25 or former. + */ +#define PG_lru_ORIGINAL (5) +#define PG_slab_ORIGINAL (7) +#define PG_private_ORIGINAL (11) /* Has something at ->private */ +#define PG_compound_ORIGINAL (14) /* Is part of a compound page */ +#define PG_swapcache_ORIGINAL (15) /* Swap page: swp_entry_t in private */ + +#define PAGE_BUDDY_MAPCOUNT_VALUE_v2_6_38 (-2) +#define PAGE_BUDDY_MAPCOUNT_VALUE_v2_6_39_to_latest_version (-128) + +#define PAGE_FLAGS_SIZE_v2_6_27_to_latest_version (4) + +#define PAGE_MAPPING_ANON (1) + +#define LSEEKED_BITMAP (1) +#define LSEEKED_PDESC (2) +#define LSEEKED_PDATA (3) + +/* + * Xen page flags + */ +#define BITS_PER_LONG (BITPERBYTE * sizeof(long)) +#define PG_shift(idx) (BITS_PER_LONG - (idx)) +#define PG_mask(x, idx) (x ## UL << PG_shift(idx)) + /* Cleared when the owning guest 'frees' this page. */ +#define PGC_allocated PG_mask(1, 1) + /* Page is Xen heap? */ +#define PGC_xen_heap PG_mask(1, 2) + /* Page is broken? */ +#define PGC_broken PG_mask(1, 7) + /* Mutually-exclusive page states: { inuse, offlining, offlined, free }. */ +#define PGC_state PG_mask(3, 9) +#define PGC_state_inuse PG_mask(0, 9) +#define PGC_state_offlining PG_mask(1, 9) +#define PGC_state_offlined PG_mask(2, 9) +#define PGC_state_free PG_mask(3, 9) +#define page_state_is(ci, st) (((ci)&PGC_state) == PGC_state_##st) + + /* Count of references to this frame. */ +#define PGC_count_width PG_shift(9) +#define PGC_count_mask ((1UL<<PGC_count_width)-1) + +/* + * Memory flags + */ +#define MEMORY_PAGETABLE_4L (1 << 0) +#define MEMORY_PAGETABLE_3L (1 << 1) +#define MEMORY_X86_PAE (1 << 2) + +/* + * Type of address + */ +enum { + VADDR, + PADDR, + VADDR_XEN, +}; + +/* + * State of mmap(2) + */ +enum { + MMAP_DISABLE, + MMAP_TRY, + MMAP_ENABLE, +}; + +static inline int +test_bit(int nr, unsigned long addr) +{ + int mask; + + mask = 1 << (nr & 0x1f); + return ((mask & addr) != 0); +} + +#define isLRU(flags) test_bit(NUMBER(PG_lru), flags) +#define isPrivate(flags) test_bit(NUMBER(PG_private), flags) +#define isCompoundHead(flags) (!!((flags) & NUMBER(PG_head_mask))) +#define isSwapCache(flags) test_bit(NUMBER(PG_swapcache), flags) +#define isSwapBacked(flags) test_bit(NUMBER(PG_swapbacked), flags) +#define isHWPOISON(flags) (test_bit(NUMBER(PG_hwpoison), flags) \ + && (NUMBER(PG_hwpoison) != NOT_FOUND_NUMBER)) + +static inline int +isAnon(unsigned long mapping) +{ + return ((unsigned long)mapping & PAGE_MAPPING_ANON) != 0; +} + +#define PTOB(X) (((unsigned long long)(X)) << PAGESHIFT()) +#define BTOP(X) (((unsigned long long)(X)) >> PAGESHIFT()) + +#define PAGESIZE() (info->page_size) +#define PAGESHIFT() (info->page_shift) +#define PAGEOFFSET(X) (((unsigned long long)(X)) & (PAGESIZE() - 1)) +#define PAGEBASE(X) (((unsigned long long)(X)) & ~(PAGESIZE() - 1)) + +/* + * for SPARSEMEM + */ +#define SECTION_SIZE_BITS() (info->section_size_bits) +#define MAX_PHYSMEM_BITS() (info->max_physmem_bits) +#define PFN_SECTION_SHIFT() (SECTION_SIZE_BITS() - PAGESHIFT()) +#define PAGES_PER_SECTION() (1UL << PFN_SECTION_SHIFT()) +#define _SECTIONS_PER_ROOT() (1) +#define _SECTIONS_PER_ROOT_EXTREME() (info->page_size / SIZE(mem_section)) +#define SECTIONS_PER_ROOT() (info->sections_per_root) +#define SECTION_ROOT_MASK() (SECTIONS_PER_ROOT() - 1) +#define SECTION_NR_TO_ROOT(sec) ((sec) / SECTIONS_PER_ROOT()) +#define SECTION_MARKED_PRESENT (1UL<<0) +#define SECTION_IS_ONLINE (1UL<<2) +/* + * SECTION_MAP_LAST_BIT was 1UL<<2 before Linux 4.13.0. + * However, we always use the higher value, because: + * 1. at least one distributor backported commit 2d070eab2e82 to kernel + * version 4.12, + * 2. it has been verified that (1UL<<2) was never set, so it is + * safe to mask that bit off even in old kernels. + */ +#define SECTION_MAP_LAST_BIT (1UL<<3) +#define SECTION_MAP_MASK (~(SECTION_MAP_LAST_BIT-1)) +#define NR_SECTION_ROOTS() divideup(num_section, SECTIONS_PER_ROOT()) +#define SECTION_NR_TO_PFN(sec) ((sec) << PFN_SECTION_SHIFT()) +#define SECTIONS_SHIFT() (MAX_PHYSMEM_BITS() - SECTION_SIZE_BITS()) +#define NR_MEM_SECTIONS() (1UL << SECTIONS_SHIFT()) + +/* + * Dump Level + */ +#define MIN_DUMP_LEVEL (0) +#define MAX_DUMP_LEVEL (31) +#define NUM_ARRAY_DUMP_LEVEL (MAX_DUMP_LEVEL + 1) /* enough to allocate + all the dump_level */ +#define DL_EXCLUDE_ZERO (0x001) /* Exclude Pages filled with Zeros */ +#define DL_EXCLUDE_CACHE (0x002) /* Exclude Cache Pages + without Private Pages */ +#define DL_EXCLUDE_CACHE_PRI (0x004) /* Exclude Cache Pages + with Private Pages */ +#define DL_EXCLUDE_USER_DATA (0x008) /* Exclude UserProcessData Pages */ +#define DL_EXCLUDE_FREE (0x010) /* Exclude Free Pages */ + + +/* + * For parse_line() + */ +#define NULLCHAR ('\0') +#define MAXARGS (100) /* max number of arguments to one function */ +#define LASTCHAR(s) (s[strlen(s)-1]) + +#define BITPERBYTE (8) +#define PGMM_CACHED (512) +#define PFN_EXCLUDED (256) +#define BUFSIZE (1024) +#define BUFSIZE_FGETS (1500) +#define BUFSIZE_BITMAP (4096) +#define PFN_BUFBITMAP (BITPERBYTE*BUFSIZE_BITMAP) +#define FILENAME_BITMAP "kdump_bitmapXXXXXX" +#define FILENAME_STDOUT "STDOUT" +#define MAP_REGION (4096*1024) + +/* + * Minimam vmcore has 2 ProgramHeaderTables(PT_NOTE and PT_LOAD). + */ +#define MIN_ELF32_HEADER_SIZE \ + sizeof(Elf32_Ehdr)+sizeof(Elf32_Phdr)+sizeof(Elf32_Phdr) +#define MIN_ELF64_HEADER_SIZE \ + sizeof(Elf64_Ehdr)+sizeof(Elf64_Phdr)+sizeof(Elf64_Phdr) +#define MIN_ELF_HEADER_SIZE \ + MAX(MIN_ELF32_HEADER_SIZE, MIN_ELF64_HEADER_SIZE) +static inline int string_exists(char *s) { return (s ? TRUE : FALSE); } +#define STREQ(A, B) (string_exists((char *)A) && \ + string_exists((char *)B) && \ + (strcmp((char *)(A), (char *)(B)) == 0)) +#define STRNEQ(A, B)(string_exists((char *)(A)) && \ + string_exists((char *)(B)) && \ + (strncmp((char *)(A), (char *)(B), strlen((char *)(B))) == 0)) + +#define UCHAR(ADDR) *((unsigned char *)(ADDR)) +#define USHORT(ADDR) *((unsigned short *)(ADDR)) +#define UINT(ADDR) *((unsigned int *)(ADDR)) +#define ULONG(ADDR) *((unsigned long *)(ADDR)) +#define ULONGLONG(ADDR) *((unsigned long long *)(ADDR)) + + +/* + * for symbol + */ +#define INVALID_SYMBOL_DATA (ULONG_MAX) +#define SYMBOL(X) (symbol_table.X) +#define SYMBOL_INIT(symbol, str_symbol) \ +do { \ + SYMBOL(symbol) = get_symbol_addr(str_symbol); \ + if (SYMBOL(symbol) != NOT_FOUND_SYMBOL) \ + SYMBOL(symbol) += info->kaslr_offset; \ +} while (0) +#define SYMBOL_INIT_NEXT(symbol, str_symbol) \ +do { \ + SYMBOL(symbol) = get_next_symbol_addr(str_symbol); \ + if (SYMBOL(symbol) != NOT_FOUND_SYMBOL) \ + SYMBOL(symbol) += info->kaslr_offset; \ +} while (0) +#define WRITE_SYMBOL(str_symbol, symbol) \ +do { \ + if (SYMBOL(symbol) != NOT_FOUND_SYMBOL) { \ + fprintf(info->file_vmcoreinfo, "%s%llx\n", \ + STR_SYMBOL(str_symbol), SYMBOL(symbol)); \ + } \ +} while (0) +#define READ_SYMBOL(str_symbol, symbol) \ +do { \ + if (SYMBOL(symbol) == NOT_FOUND_SYMBOL) { \ + SYMBOL(symbol) = read_vmcoreinfo_symbol(STR_SYMBOL(str_symbol)); \ + if (SYMBOL(symbol) == INVALID_SYMBOL_DATA) \ + return FALSE; \ + if (info->read_text_vmcoreinfo && \ + (SYMBOL(symbol) != NOT_FOUND_SYMBOL) && \ + (SYMBOL(symbol) != INVALID_SYMBOL_DATA)) \ + SYMBOL(symbol) += info->kaslr_offset; \ + } \ +} while (0) + +/* + * for structure + */ +#define SIZE(X) (size_table.X) +#define OFFSET(X) (offset_table.X) +#define ARRAY_LENGTH(X) (array_table.X) +#define SIZE_INIT(X, Y) \ +do { \ + if ((SIZE(X) = get_structure_size(Y, DWARF_INFO_GET_STRUCT_SIZE)) \ + == FAILED_DWARFINFO) \ + return FALSE; \ +} while (0) +#define TYPEDEF_SIZE_INIT(X, Y) \ +do { \ + if ((SIZE(X) = get_structure_size(Y, DWARF_INFO_GET_TYPEDEF_SIZE)) \ + == FAILED_DWARFINFO) \ + return FALSE; \ +} while (0) +#define ENUM_TYPE_SIZE_INIT(X, Y) \ +do { \ + if ((SIZE(X) = get_structure_size(Y, \ + DWARF_INFO_GET_ENUMERATION_TYPE_SIZE)) \ + == FAILED_DWARFINFO) \ + return FALSE; \ +} while (0) +#define OFFSET_INIT(X, Y, Z) \ +do { \ + if ((OFFSET(X) = get_member_offset(Y, Z, DWARF_INFO_GET_MEMBER_OFFSET)) \ + == FAILED_DWARFINFO) \ + return FALSE; \ +} while (0) +#define SYMBOL_ARRAY_LENGTH_INIT(X, Y) \ +do { \ + if ((ARRAY_LENGTH(X) = get_array_length(Y, NULL, DWARF_INFO_GET_SYMBOL_ARRAY_LENGTH)) == FAILED_DWARFINFO) \ + return FALSE; \ +} while (0) +#define SYMBOL_ARRAY_TYPE_INIT(X, Y) \ +do { \ + if ((ARRAY_LENGTH(X) = get_array_length(Y, NULL, DWARF_INFO_CHECK_SYMBOL_ARRAY_TYPE)) == FAILED_DWARFINFO) \ + return FALSE; \ +} while (0) +#define MEMBER_ARRAY_LENGTH_INIT(X, Y, Z) \ +do { \ + if ((ARRAY_LENGTH(X) = get_array_length(Y, Z, DWARF_INFO_GET_MEMBER_ARRAY_LENGTH)) == FAILED_DWARFINFO) \ + return FALSE; \ +} while (0) + +#define WRITE_STRUCTURE_SIZE(str_structure, structure) \ +do { \ + if (SIZE(structure) != NOT_FOUND_STRUCTURE) { \ + fprintf(info->file_vmcoreinfo, "%s%ld\n", \ + STR_SIZE(str_structure), SIZE(structure)); \ + } \ +} while (0) +#define WRITE_MEMBER_OFFSET(str_member, member) \ +do { \ + if (OFFSET(member) != NOT_FOUND_STRUCTURE) { \ + fprintf(info->file_vmcoreinfo, "%s%ld\n", \ + STR_OFFSET(str_member), OFFSET(member)); \ + } \ +} while (0) +#define WRITE_ARRAY_LENGTH(str_array, array) \ +do { \ + if (ARRAY_LENGTH(array) != NOT_FOUND_STRUCTURE) { \ + fprintf(info->file_vmcoreinfo, "%s%ld\n", \ + STR_LENGTH(str_array), ARRAY_LENGTH(array)); \ + } \ +} while (0) +#define READ_STRUCTURE_SIZE(str_structure, structure) \ +do { \ + if (SIZE(structure) == NOT_FOUND_STRUCTURE) { \ + SIZE(structure) = read_vmcoreinfo_long(STR_SIZE(str_structure)); \ + if (SIZE(structure) == INVALID_STRUCTURE_DATA) \ + return FALSE; \ + } \ +} while (0) +#define READ_MEMBER_OFFSET(str_member, member) \ +do { \ + if (OFFSET(member) == NOT_FOUND_STRUCTURE) { \ + OFFSET(member) = read_vmcoreinfo_long(STR_OFFSET(str_member)); \ + if (OFFSET(member) == INVALID_STRUCTURE_DATA) \ + return FALSE; \ + } \ +} while (0) +#define READ_ARRAY_LENGTH(str_array, array) \ +do { \ + if (ARRAY_LENGTH(array) == NOT_FOUND_STRUCTURE) { \ + ARRAY_LENGTH(array) = read_vmcoreinfo_long(STR_LENGTH(str_array)); \ + if (ARRAY_LENGTH(array) == INVALID_STRUCTURE_DATA) \ + return FALSE; \ + } \ +} while (0) + +/* + * for number + */ +#define NUMBER(X) (number_table.X) + +#define ENUM_NUMBER_INIT(number, str_number) \ +do {\ + NUMBER(number) = get_enum_number(str_number); \ + if (NUMBER(number) == FAILED_DWARFINFO) \ + return FALSE; \ +} while (0) +#define WRITE_NUMBER(str_number, number) \ +do { \ + if (NUMBER(number) != NOT_FOUND_NUMBER) { \ + fprintf(info->file_vmcoreinfo, "%s%ld\n", \ + STR_NUMBER(str_number), NUMBER(number)); \ + } \ +} while (0) +#define READ_NUMBER(str_number, number) \ +do { \ + if (NUMBER(number) == NOT_FOUND_NUMBER) { \ + NUMBER(number) = read_vmcoreinfo_long(STR_NUMBER(str_number)); \ + if (NUMBER(number) == INVALID_STRUCTURE_DATA) \ + return FALSE; \ + } \ +} while (0) +#define WRITE_NUMBER_UNSIGNED(str_number, number) \ +do { \ + if (NUMBER(number) != NOT_FOUND_NUMBER) { \ + fprintf(info->file_vmcoreinfo, "%s%lu\n", \ + STR_NUMBER(str_number), NUMBER(number)); \ + } \ +} while (0) +#define READ_NUMBER_UNSIGNED(str_number, number) \ +do { \ + if (NUMBER(number) == NOT_FOUND_NUMBER) { \ + NUMBER(number) = read_vmcoreinfo_ulong(STR_NUMBER(str_number)); \ + if (NUMBER(number) == INVALID_STRUCTURE_DATA) \ + return FALSE; \ + } \ +} while (0) + + +/* + * for source file name + */ +#define SRCFILE(X) (srcfile_table.X) +#define TYPEDEF_SRCFILE_INIT(decl_name, str_decl_name) \ +do { \ + get_source_filename(str_decl_name, SRCFILE(decl_name), DWARF_INFO_GET_TYPEDEF_SRCNAME); \ +} while (0) + +#define WRITE_SRCFILE(str_decl_name, decl_name) \ +do { \ + if (strlen(SRCFILE(decl_name))) { \ + fprintf(info->file_vmcoreinfo, "%s%s\n", \ + STR_SRCFILE(str_decl_name), SRCFILE(decl_name)); \ + } \ +} while (0) + +#define READ_SRCFILE(str_decl_name, decl_name) \ +do { \ + if (strlen(SRCFILE(decl_name)) == 0) { \ + if (!read_vmcoreinfo_string(STR_SRCFILE(str_decl_name), SRCFILE(decl_name))) \ + return FALSE; \ + } \ +} while (0) + +/* + * Macro for getting splitting info. + */ +#define SPLITTING_DUMPFILE(i) info->splitting_info[i].name_dumpfile +#define SPLITTING_FD_BITMAP(i) info->splitting_info[i].fd_bitmap +#define SPLITTING_START_PFN(i) info->splitting_info[i].start_pfn +#define SPLITTING_END_PFN(i) info->splitting_info[i].end_pfn +#define SPLITTING_OFFSET_EI(i) info->splitting_info[i].offset_eraseinfo +#define SPLITTING_SIZE_EI(i) info->splitting_info[i].size_eraseinfo + +/* + * Macro for getting parallel info. + */ +#define FD_MEMORY_PARALLEL(i) info->parallel_info[i].fd_memory +#define FD_BITMAP_MEMORY_PARALLEL(i) info->parallel_info[i].fd_bitmap_memory +#define FD_BITMAP_PARALLEL(i) info->parallel_info[i].fd_bitmap +#define BUF_PARALLEL(i) info->parallel_info[i].buf +#define BUF_OUT_PARALLEL(i) info->parallel_info[i].buf_out +#define MMAP_CACHE_PARALLEL(i) info->parallel_info[i].mmap_cache +#define ZLIB_STREAM_PARALLEL(i) info->parallel_info[i].zlib_stream +#ifdef USELZO +#define WRKMEM_PARALLEL(i) info->parallel_info[i].wrkmem +#endif +/* + * kernel version + * + * NOTE: the format of kernel_version is as follows + * 8 bits major version + * 8 bits minor version + * 16 bits release + * so version 2.6.18 would be encoded as 0x02060012 + * These macros will let us decode that easier + */ +#define KVER_MAJ_SHIFT 24 +#define KVER_MIN_SHIFT 16 +#define KERNEL_VERSION(x,y,z) (((x) << KVER_MAJ_SHIFT) | ((y) << KVER_MIN_SHIFT) | (z)) +#define OLDEST_VERSION KERNEL_VERSION(2, 6, 15)/* linux-2.6.15 */ +#define LATEST_VERSION KERNEL_VERSION(4, 17, 0)/* linux-4.17.0 */ + +/* + * vmcoreinfo in /proc/vmcore + */ +#define VMCOREINFO_BYTES (4096) +#define FILENAME_VMCOREINFO "/tmp/vmcoreinfoXXXXXX" + +/* + * field name of vmcoreinfo file + */ +#define STR_OSRELEASE "OSRELEASE=" +#define STR_PAGESIZE "PAGESIZE=" +#define STR_CRASHTIME "CRASHTIME=" +#define STR_SYMBOL(X) "SYMBOL("X")=" +#define STR_SIZE(X) "SIZE("X")=" +#define STR_OFFSET(X) "OFFSET("X")=" +#define STR_LENGTH(X) "LENGTH("X")=" +#define STR_NUMBER(X) "NUMBER("X")=" +#define STR_SRCFILE(X) "SRCFILE("X")=" +#define STR_CONFIG_X86_PAE "CONFIG_X86_PAE=y" +#define STR_CONFIG_PGTABLE_4 "CONFIG_PGTABLE_4=y" +#define STR_CONFIG_PGTABLE_3 "CONFIG_PGTABLE_3=y" +#define STR_KERNELOFFSET "KERNELOFFSET=" + +/* + * common value + */ +#define NOSPACE (-1) /* code of write-error due to nospace */ +#define DEFAULT_ORDER (4) +#define TIMEOUT_STDIN (600) +#define SIZE_BUF_STDIN (4096) +#define STRLEN_OSRELEASE (65) /* same length as diskdump.h */ + +/* + * The value of dependence on machine + */ +#define PAGE_OFFSET (info->page_offset) +#define VMALLOC_START (info->vmalloc_start) +#define VMALLOC_END (info->vmalloc_end) +#define VMEMMAP_START (info->vmemmap_start) +#define VMEMMAP_END (info->vmemmap_end) +#define PMASK (0x7ffffffffffff000UL) + +#ifdef __aarch64__ +unsigned long get_kvbase_arm64(void); +#define KVBASE get_kvbase_arm64() +#endif /* aarch64 */ + +#ifdef __arm__ +#define KVBASE_MASK (0xffff) +#define KVBASE (SYMBOL(_stext) & ~KVBASE_MASK) +#define _SECTION_SIZE_BITS (28) +#define _MAX_PHYSMEM_BITS (32) +#define ARCH_PFN_OFFSET (info->phys_base >> PAGESHIFT()) + +#define PTRS_PER_PTE (512) +#define PGDIR_SHIFT (21) +#define PMD_SHIFT (21) +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE - 1)) + +#define _PAGE_PRESENT (1 << 0) + +#endif /* arm */ + +#ifdef __x86__ +#define __PAGE_OFFSET (0xc0000000) +#define __VMALLOC_RESERVE (128 << 20) +#define MAXMEM (-PAGE_OFFSET-__VMALLOC_RESERVE) +#define KVBASE_MASK (0x7fffff) +#define KVBASE (SYMBOL(_stext) & ~KVBASE_MASK) +#define _SECTION_SIZE_BITS (26) +#define _SECTION_SIZE_BITS_PAE_ORIG (30) +#define _SECTION_SIZE_BITS_PAE_2_6_26 (29) +#define _MAX_PHYSMEM_BITS (32) +#define _MAX_PHYSMEM_BITS_PAE (36) + +#define PGDIR_SHIFT_3LEVEL (30) +#define PTRS_PER_PTE_3LEVEL (512) +#define PTRS_PER_PGD_3LEVEL (4) +#define PMD_SHIFT (21) /* only used by PAE translators */ +#define PTRS_PER_PMD (512) /* only used by PAE translators */ +#define PTE_SHIFT (12) /* only used by PAE translators */ +#define PTRS_PER_PTE (512) /* only used by PAE translators */ + +#define pgd_index_PAE(address) (((address) >> PGDIR_SHIFT_3LEVEL) & (PTRS_PER_PGD_3LEVEL - 1)) +#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) +#define pte_index(address) (((address) >> PTE_SHIFT) & (PTRS_PER_PTE - 1)) + +#define _PAGE_PRESENT (0x001) +#define _PAGE_PSE (0x080) + +/* Physical addresses are up to 52 bits (AMD64). + * Mask off bits 52-62 (reserved) and bit 63 (NX). + */ +#define ENTRY_MASK (~0xfff0000000000fffULL) + +#endif /* x86 */ + +#ifdef __x86_64__ +#define __PAGE_OFFSET_ORIG (0xffff810000000000) /* 2.6.26, or former */ +#define __PAGE_OFFSET_2_6_27 (0xffff880000000000) /* 2.6.27, or later */ +#define __PAGE_OFFSET_5LEVEL (0xff10000000000000) /* 5-level page table */ + +#define VMALLOC_START_ORIG (0xffffc20000000000) /* 2.6.30, or former */ +#define VMALLOC_START_2_6_31 (0xffffc90000000000) /* 2.6.31, or later */ +#define VMALLOC_START_5LEVEL (0xffa0000000000000) /* 5-level page table */ +#define VMALLOC_END_ORIG (0xffffe1ffffffffff) /* 2.6.30, or former */ +#define VMALLOC_END_2_6_31 (0xffffe8ffffffffff) /* 2.6.31, or later */ +#define VMALLOC_END_5LEVEL (0xffd1ffffffffffff) /* 5-level page table */ + +#define VMEMMAP_START_ORIG (0xffffe20000000000) /* 2.6.30, or former */ +#define VMEMMAP_START_2_6_31 (0xffffea0000000000) /* 2.6.31, or later */ +#define VMEMMAP_START_5LEVEL (0xffd4000000000000) /* 5-level page table */ +#define VMEMMAP_END_ORIG (0xffffe2ffffffffff) /* 2.6.30, or former */ +#define VMEMMAP_END_2_6_31 (0xffffeaffffffffff) /* 2.6.31, or later */ +#define VMEMMAP_END_5LEVEL (0xffd5ffffffffffff) /* 5-level page table */ + +#define __START_KERNEL_map (0xffffffff80000000) +#define KVBASE PAGE_OFFSET +#define _SECTION_SIZE_BITS (27) +#define _MAX_PHYSMEM_BITS_ORIG (40) +#define _MAX_PHYSMEM_BITS_2_6_26 (44) +#define _MAX_PHYSMEM_BITS_2_6_31 (46) +#define _MAX_PHYSMEM_BITS_5LEVEL (52) + +/* + * 4 Levels paging + */ +#define PGD_SHIFT (39) +#define PUD_SHIFT (30) +#define PMD_SHIFT (21) +#define PTE_SHIFT (12) + +#define PTRS_PER_PGD (512) +#define PTRS_PER_PUD (512) +#define PTRS_PER_PMD (512) +#define PTRS_PER_PTE (512) + +#define PUD_SIZE (1UL << PUD_SHIFT) +#define PUD_MASK (~(PUD_SIZE - 1)) +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE - 1)) + +/* + * 5 Levels paging + */ +#define PGD_SHIFT_5LEVEL (48) +#define P4D_SHIFT (39) + +#define PTRS_PER_PGD_5LEVEL (512) +#define PTRS_PER_P4D (512) + +#define pgd5_index(address) (((address) >> PGD_SHIFT_5LEVEL) & (PTRS_PER_PGD_5LEVEL - 1)) +#define pgd_index(address) (((address) >> PGD_SHIFT) & (PTRS_PER_PGD - 1)) +#define p4d_index(address) (((address) >> P4D_SHIFT) & (PTRS_PER_P4D - 1)) +#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) +#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) +#define pte_index(address) (((address) >> PTE_SHIFT) & (PTRS_PER_PTE - 1)) + +#define _PAGE_PRESENT (0x001) +#define _PAGE_PSE (0x080) /* 2MB or 1GB page */ + +#endif /* x86_64 */ + +#ifdef __powerpc64__ +#define __PAGE_OFFSET (0xc000000000000000) +#define KERNELBASE PAGE_OFFSET +#define VMALLOCBASE (0xD000000000000000) +#define KVBASE (SYMBOL(_stext)) +#define _SECTION_SIZE_BITS (24) +#define _MAX_PHYSMEM_BITS_ORIG (44) +#define _MAX_PHYSMEM_BITS_3_7 (46) +#define REGION_SHIFT (60UL) +#define VMEMMAP_REGION_ID (0xfUL) + +/* 4-level page table support */ + +/* 4K pagesize */ +#define PTE_INDEX_SIZE_L4_4K 9 +#define PMD_INDEX_SIZE_L4_4K 7 +#define PUD_INDEX_SIZE_L4_4K 7 +#define PGD_INDEX_SIZE_L4_4K 9 +#define PUD_INDEX_SIZE_L4_4K_3_7 9 +#define PTE_INDEX_SIZE_RADIX_4K 9 +#define PMD_INDEX_SIZE_RADIX_4K 9 +#define PUD_INDEX_SIZE_RADIX_4K 9 +#define PGD_INDEX_SIZE_RADIX_4K 13 +#define PTE_RPN_SHIFT_L4_4K 17 +#define PTE_RPN_SHIFT_L4_4K_4_5 18 +#define PGD_MASKED_BITS_4K 0 +#define PUD_MASKED_BITS_4K 0 +#define PMD_MASKED_BITS_4K 0 + +/* 64K pagesize */ +#define PTE_INDEX_SIZE_L4_64K 12 +#define PMD_INDEX_SIZE_L4_64K 12 +#define PUD_INDEX_SIZE_L4_64K 0 +#define PGD_INDEX_SIZE_L4_64K 4 +#define PTE_INDEX_SIZE_L4_64K_3_10 8 +#define PMD_INDEX_SIZE_L4_64K_3_10 10 +#define PGD_INDEX_SIZE_L4_64K_3_10 12 +#define PMD_INDEX_SIZE_L4_64K_4_6 5 +#define PUD_INDEX_SIZE_L4_64K_4_6 5 +#define PMD_INDEX_SIZE_L4_64K_4_12 10 +#define PUD_INDEX_SIZE_L4_64K_4_12 7 +#define PGD_INDEX_SIZE_L4_64K_4_12 8 +#define PUD_INDEX_SIZE_L4_64K_4_17 10 +#define PTE_INDEX_SIZE_RADIX_64K 5 +#define PMD_INDEX_SIZE_RADIX_64K 9 +#define PUD_INDEX_SIZE_RADIX_64K 9 +#define PGD_INDEX_SIZE_RADIX_64K 13 +#define PTE_RPN_SHIFT_L4_64K_V1 32 +#define PTE_RPN_SHIFT_L4_64K_V2 30 +#define PGD_MASKED_BITS_64K 0 +#define PUD_MASKED_BITS_64K 0x1ff +#define PMD_MASKED_BITS_64K 0x1ff +#define PMD_MASKED_BITS_64K_3_11 0xfff +#define PGD_MASKED_BITS_64K_4_6 0xc0000000000000ffUL +#define PUD_MASKED_BITS_64K_4_6 0xc0000000000000ffUL +#define PMD_MASKED_BITS_64K_4_6 0xc0000000000000ffUL + +#define PTE_RPN_MASK_DEFAULT 0xffffffffffffffffUL +#define PTE_RPN_SIZE_L4_4_6 (info->page_size == 65536 ? 41 : 45) +#define PTE_RPN_MASK_L4_4_6 (((1UL << PTE_RPN_SIZE_L4_4_6) - 1) << info->page_shift) +#define PTE_RPN_SHIFT_L4_4_6 info->page_shift + +#define PGD_MASKED_BITS_4_7 0xc0000000000000ffUL +#define PUD_MASKED_BITS_4_7 0xc0000000000000ffUL +#define PMD_MASKED_BITS_4_7 0xc0000000000000ffUL + +#define PTE_RPN_SIZE_L4_4_11 53 +#define PTE_RPN_MASK_L4_4_11 \ + (((1UL << PTE_RPN_SIZE_L4_4_11) - 1) & ~((1UL << info->page_shift) - 1)) +#define PTE_RPN_SHIFT_L4_4_11 info->page_shift + +/* + * Supported MMU types + */ +#define STD_MMU 0x0 +/* + * The flag bit for radix MMU in cpu_spec.mmu_features + * in the kernel. Use the same flag here. + */ +#define RADIX_MMU 0x40 + + +#define PGD_MASK_L4 \ + (info->kernel_version >= KERNEL_VERSION(3, 10, 0) ? (info->ptrs_per_pgd - 1) : 0x1ff) +#define PGD_OFFSET_L4(vaddr) ((vaddr >> (info->l4_shift)) & PGD_MASK_L4) + +#define PUD_OFFSET_L4(vaddr) \ + ((vaddr >> (info->l3_shift)) & (info->ptrs_per_l3 - 1)) + +#define PMD_OFFSET_L4(vaddr) \ + ((vaddr >> (info->l2_shift)) & (info->ptrs_per_l2 - 1)) + +#define _PAGE_PRESENT \ + (info->kernel_version >= KERNEL_VERSION(4, 6, 0) ? \ + (0x1UL << 63) : (info->kernel_version >= KERNEL_VERSION(4, 5, 0) ? \ + 0x2UL : 0x1UL)) + +#endif + +#ifdef __powerpc32__ + +#define __PAGE_OFFSET (0xc0000000) +#define KERNELBASE PAGE_OFFSET +#define VMALL_START (info->vmalloc_start) +#define KVBASE (SYMBOL(_stext)) +#define _SECTION_SIZE_BITS (24) +#define _MAX_PHYSMEM_BITS (44) + +#endif + +#ifdef __s390x__ +#define __PAGE_OFFSET (info->page_size - 1) +#define KERNELBASE (0) +#define KVBASE KERNELBASE +#define _SECTION_SIZE_BITS (28) +#define _MAX_PHYSMEM_BITS_ORIG (42) +#define _MAX_PHYSMEM_BITS_3_3 (46) + +/* Bits in the segment/region table address-space-control-element */ +#define _ASCE_TYPE_MASK 0x0c +#define _ASCE_TABLE_LENGTH 0x03 /* region table length */ + +#define TABLE_LEVEL(x) (((x) & _ASCE_TYPE_MASK) >> 2) +#define TABLE_LENGTH(x) ((x) & _ASCE_TABLE_LENGTH) + +/* Bits in the region table entry */ +#define _REGION_ENTRY_ORIGIN ~0xfffUL /* region table origin*/ +#define _REGION_ENTRY_TYPE_MASK 0x0c /* region table type mask */ +#define _REGION_ENTRY_INVALID 0x20 /* invalid region table entry */ +#define _REGION_ENTRY_LENGTH 0x03 /* region table length */ +#define _REGION_ENTRY_LARGE 0x400 +#define _REGION_OFFSET_MASK 0x7ffUL /* region/segment table offset mask */ + +#define RSG_TABLE_LEVEL(x) (((x) & _REGION_ENTRY_TYPE_MASK) >> 2) +#define RSG_TABLE_LENGTH(x) ((x) & _REGION_ENTRY_LENGTH) + +/* Bits in the segment table entry */ +#define _SEGMENT_ENTRY_ORIGIN ~0x7ffUL +#define _SEGMENT_ENTRY_LARGE 0x400 +#define _SEGMENT_ENTRY_CO 0x100 +#define _SEGMENT_PAGE_SHIFT 31 +#define _SEGMENT_INDEX_SHIFT 20 + +/* Hardware bits in the page table entry */ +#define _PAGE_ZERO 0x800 /* Bit pos 52 must conatin zero */ +#define _PAGE_INVALID 0x400 /* HW invalid bit */ +#define _PAGE_INDEX_SHIFT 12 +#define _PAGE_OFFSET_MASK 0xffUL /* page table offset mask */ + +#endif /* __s390x__ */ + +#ifdef __ia64__ /* ia64 */ +#define REGION_SHIFT (61) + +#define KERNEL_CACHED_REGION (7) +#define KERNEL_UNCACHED_REGION (6) +#define KERNEL_VMALLOC_REGION (5) +#define USER_STACK_REGION (4) +#define USER_DATA_REGION (3) +#define USER_TEXT_REGION (2) +#define USER_SHMEM_REGION (1) +#define USER_IA32_EMUL_REGION (0) + +#define KERNEL_CACHED_BASE ((unsigned long)KERNEL_CACHED_REGION << REGION_SHIFT) +#define KERNEL_UNCACHED_BASE ((unsigned long)KERNEL_UNCACHED_REGION << REGION_SHIFT) +#define KERNEL_VMALLOC_BASE ((unsigned long)KERNEL_VMALLOC_REGION << REGION_SHIFT) + +#define KVBASE KERNEL_VMALLOC_BASE +#define _PAGE_SIZE_64M (26) +#define KERNEL_TR_PAGE_SIZE (1 << _PAGE_SIZE_64M) +#define KERNEL_TR_PAGE_MASK (~(KERNEL_TR_PAGE_SIZE - 1)) +#define DEFAULT_PHYS_START (KERNEL_TR_PAGE_SIZE * 1) +#define _SECTION_SIZE_BITS (30) +#define _MAX_PHYSMEM_BITS (50) + +/* + * 3 Levels paging + */ +#define _PAGE_PPN_MASK (((1UL << _MAX_PHYSMEM_BITS) - 1) & ~0xfffUL) +#define PTRS_PER_PTD_SHIFT (PAGESHIFT() - 3) + +#define PMD_SHIFT (PAGESHIFT() + PTRS_PER_PTD_SHIFT) +#define PGDIR_SHIFT_3L (PMD_SHIFT + PTRS_PER_PTD_SHIFT) + +#define MASK_POFFSET ((1UL << PAGESHIFT()) - 1) +#define MASK_PTE ((1UL << PMD_SHIFT) - 1) &~((1UL << PAGESHIFT()) - 1) +#define MASK_PMD ((1UL << PGDIR_SHIFT_3L) - 1) &~((1UL << PMD_SHIFT) - 1) +#define MASK_PGD_3L ((1UL << REGION_SHIFT) - 1) & (~((1UL << PGDIR_SHIFT_3L) - 1)) + +/* + * 4 Levels paging + */ +#define PUD_SHIFT (PMD_SHIFT + PTRS_PER_PTD_SHIFT) +#define PGDIR_SHIFT_4L (PUD_SHIFT + PTRS_PER_PTD_SHIFT) + +#define MASK_PUD ((1UL << REGION_SHIFT) - 1) & (~((1UL << PUD_SHIFT) - 1)) +#define MASK_PGD_4L ((1UL << REGION_SHIFT) - 1) & (~((1UL << PGDIR_SHIFT_4L) - 1)) + +/* + * Key for distinguishing PGTABLE_3L or PGTABLE_4L. + */ +#define STR_PUD_T_3L "include/asm-generic/pgtable-nopud.h" +#define STR_PUD_T_4L "include/asm/page.h" + +#endif /* ia64 */ + +#ifdef __sparc64__ + +#define KVBASE (SYMBOL(_stext)) +#define KVBASE_MASK (0xffff) +#define _SECTION_SIZE_BITS (30) +#define _MAX_PHYSMEM_BITS_L3 (49) +#define _MAX_PHYSMEM_BITS_L4 (53) +#define VMALLOC_START_SPARC64 (0x0000000100000000UL) +#define VMEMMAP_BASE_SPARC64 (0x0000010000000000UL) +#define VMEMMAP_CHUNK_SHIFT (22) +#define VMEMMAP_CHUNK (1UL << VMEMMAP_CHUNK_SHIFT) +#define VMEMMAP_CHUNK_MASK (~(VMEMMAP_CHUNK - 1UL)) + +#define PAGE_SHIFT 13 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE - 1)) + +#define MAX_PHYS_ADDRESS_LOBITS (41) +#define NR_CHUNKS_SHIFT (MAX_PHYS_ADDRESS_LOBITS - PAGE_SHIFT + 6) +#define NR_CHUNKS_MASK (~((1UL << NR_CHUNKS_SHIFT) - 1)) + +#define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT - 3)) +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE - 1)) +#define PMD_BITS (PAGE_SHIFT - 3) + +#define PUD_SHIFT (PMD_SHIFT + PMD_BITS) +#define PUD_SIZE (1UL << PUD_SHIFT) +#define PUD_MASK (~(PUD_SIZE - 1)) +#define PUD_BITS (PAGE_SHIFT - 3) + +#define PGDIR_SHIFT_L4 (PUD_SHIFT + PUD_BITS) +#define PGDIR_SIZE_L4 (1UL << PGDIR_SHIFT_L4) +#define PGDIR_MASK_L4 (~(PGDIR_SIZE_L4 - 1)) + +#define PGDIR_SHIFT_L3 (PMD_SHIFT + PMD_BITS) +#define PGDIR_SIZE_L3 (1UL << PGDIR_SHIFT_L3) +#define PGDIR_MASK_L3 (~(PGDIR_SIZE_L3 - 1)) + +#define PGDIR_BITS (PAGE_SHIFT - 3) + +#define PTRS_PER_PTE (1UL << (PAGE_SHIFT - 3)) +#define PTRS_PER_PMD (1UL << PMD_BITS) +#define PTRS_PER_PUD (1UL << PUD_BITS) +#define PTRS_PER_PGD (1UL << PGDIR_BITS) + +#define _PAGE_PMD_HUGE (0x0100000000000000UL) +#define _PAGE_PUD_HUGE _PAGE_PMD_HUGE +#define _PAGE_PADDR_4V (0x00FFFFFFFFFFE000UL) +#define _PAGE_PRESENT_4V (0x0000000000000010UL) + +typedef unsigned long pte_t; +typedef unsigned long pmd_t; +typedef unsigned long pud_t; +typedef unsigned long pgd_t; + +#define pud_none(pud) (!(pud)) +#define pgd_none(pgd) (!(pgd)) +#define pmd_none(pmd) (!(pmd)) + +#define pte_to_pa(pte) (pte & _PAGE_PADDR_4V) + +#define pgd_index_l4(addr) (((addr) >> PGDIR_SHIFT_L4) & (PTRS_PER_PGD - 1)) +#define pgd_offset_l4(pgdir,addr) ((unsigned long) \ + ((pgd_t *)pgdir + pgd_index_l4(addr))) + +#define pgd_index_l3(addr) (((addr) >> PGDIR_SHIFT_L3) & (PTRS_PER_PGD - 1)) +#define pgd_offset_l3(pgdir,addr) ((unsigned long) \ + ((pgd_t *)pgdir + pgd_index_l3(addr))) + +#define pud_index(addr) (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) +#define pud_offset(pgdp, addr) ((unsigned long) \ + ((pud_t *)pgdp + pud_index(addr))) +#define pud_large(pud) (pud & _PAGE_PUD_HUGE) + +#define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) +#define pmd_offset(pudp, addr) ((unsigned long) \ + ((pmd_t *)pudp + pmd_index(addr))) +#define pmd_large(pmd) (pmd & _PAGE_PMD_HUGE) + +#define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) +#define pte_offset(pmdp, addr) ((unsigned long) \ + ((pte_t *)(pte_to_pa(pmdp) + pte_index(addr)))) +#define pte_present(pte) (pte & _PAGE_PRESENT_4V) + +#endif /* sparc64 */ + +/* + * The function of dependence on machine + */ +static inline int stub_true() { return TRUE; } +static inline int stub_true_ul(unsigned long x) { return TRUE; } +static inline int stub_false() { return FALSE; } +#ifdef __aarch64__ +int get_phys_base_arm64(void); +int get_machdep_info_arm64(void); +unsigned long long vaddr_to_paddr_arm64(unsigned long vaddr); +int get_versiondep_info_arm64(void); +int get_xen_basic_info_arm64(void); +int get_xen_info_arm64(void); +#define find_vmemmap() stub_false() +#define vaddr_to_paddr(X) vaddr_to_paddr_arm64(X) +#define get_phys_base() get_phys_base_arm64() +#define get_machdep_info() get_machdep_info_arm64() +#define get_versiondep_info() get_versiondep_info_arm64() +#define get_kaslr_offset(X) stub_false() +#define get_xen_basic_info_arch(X) get_xen_basic_info_arm64(X) +#define get_xen_info_arch(X) get_xen_info_arm64(X) +#define is_phys_addr(X) stub_true_ul(X) +#define arch_crashkernel_mem_size() stub_false() +#endif /* aarch64 */ + +#ifdef __arm__ +int get_phys_base_arm(void); +int get_machdep_info_arm(void); +unsigned long long vaddr_to_paddr_arm(unsigned long vaddr); +#define find_vmemmap() stub_false() +#define get_phys_base() get_phys_base_arm() +#define get_machdep_info() get_machdep_info_arm() +#define get_versiondep_info() stub_true() +#define get_kaslr_offset(X) stub_false() +#define vaddr_to_paddr(X) vaddr_to_paddr_arm(X) +#define is_phys_addr(X) stub_true_ul(X) +#define arch_crashkernel_mem_size() stub_false() +#endif /* arm */ + +#ifdef __x86__ +int get_machdep_info_x86(void); +int get_versiondep_info_x86(void); +unsigned long long vaddr_to_paddr_x86(unsigned long vaddr); +#define find_vmemmap() stub_false() +#define get_phys_base() stub_true() +#define get_machdep_info() get_machdep_info_x86() +#define get_versiondep_info() get_versiondep_info_x86() +#define get_kaslr_offset(X) stub_false() +#define vaddr_to_paddr(X) vaddr_to_paddr_x86(X) +#define is_phys_addr(X) stub_true_ul(X) +#define arch_crashkernel_mem_size() stub_false() +#endif /* x86 */ + +#ifdef __x86_64__ +unsigned long get_kaslr_offset_x86_64(unsigned long vaddr); +int get_phys_base_x86_64(void); +int get_machdep_info_x86_64(void); +int get_versiondep_info_x86_64(void); +unsigned long long vtop4_x86_64(unsigned long vaddr); +unsigned long long vtop4_x86_64_pagetable(unsigned long vaddr, unsigned long pagetable); +#define find_vmemmap() find_vmemmap_x86_64() +#define get_phys_base() get_phys_base_x86_64() +#define get_machdep_info() get_machdep_info_x86_64() +#define get_versiondep_info() get_versiondep_info_x86_64() +#define get_kaslr_offset(X) get_kaslr_offset_x86_64(X) +#define vaddr_to_paddr(X) vtop4_x86_64(X) +#define is_phys_addr(X) stub_true_ul(X) +#define arch_crashkernel_mem_size() stub_false() +#endif /* x86_64 */ + +#ifdef __powerpc64__ /* powerpc64 */ +int get_machdep_info_ppc64(void); +int get_versiondep_info_ppc64(void); +unsigned long long vaddr_to_paddr_ppc64(unsigned long vaddr); +int arch_crashkernel_mem_size_ppc64(void); +#define find_vmemmap() stub_false() +#define get_phys_base() stub_true() +#define get_machdep_info() get_machdep_info_ppc64() +#define get_versiondep_info() get_versiondep_info_ppc64() +#define get_kaslr_offset(X) stub_false() +#define vaddr_to_paddr(X) vaddr_to_paddr_ppc64(X) +#define is_phys_addr(X) stub_true_ul(X) +#define arch_crashkernel_mem_size() arch_crashkernel_mem_size_ppc64() +#endif /* powerpc64 */ + +#ifdef __powerpc32__ /* powerpc32 */ +int get_machdep_info_ppc(void); +unsigned long long vaddr_to_paddr_ppc(unsigned long vaddr); +#define find_vmemmap() stub_false() +#define get_phys_base() stub_true() +#define get_machdep_info() get_machdep_info_ppc() +#define get_versiondep_info() stub_true() +#define get_kaslr_offset(X) stub_false() +#define vaddr_to_paddr(X) vaddr_to_paddr_ppc(X) +#define is_phys_addr(X) stub_true_ul(X) +#define arch_crashkernel_mem_size() stub_false() +#endif /* powerpc32 */ + +#ifdef __s390x__ /* s390x */ +int get_machdep_info_s390x(void); +unsigned long long vaddr_to_paddr_s390x(unsigned long vaddr); +int is_iomem_phys_addr_s390x(unsigned long addr); +#define find_vmemmap() stub_false() +#define get_phys_base() stub_true() +#define get_machdep_info() get_machdep_info_s390x() +#define get_versiondep_info() stub_true() +#define get_kaslr_offset(X) stub_false() +#define vaddr_to_paddr(X) vaddr_to_paddr_s390x(X) +#define is_phys_addr(X) is_iomem_phys_addr_s390x(X) +#define arch_crashkernel_mem_size() stub_false() +#endif /* s390x */ + +#ifdef __ia64__ /* ia64 */ +int get_phys_base_ia64(void); +int get_machdep_info_ia64(void); +unsigned long long vaddr_to_paddr_ia64(unsigned long vaddr); +#define find_vmemmap() stub_false() +#define get_machdep_info() get_machdep_info_ia64() +#define get_phys_base() get_phys_base_ia64() +#define get_versiondep_info() stub_true() +#define get_kaslr_offset(X) stub_false() +#define vaddr_to_paddr(X) vaddr_to_paddr_ia64(X) +#define VADDR_REGION(X) (((unsigned long)(X)) >> REGION_SHIFT) +#define is_phys_addr(X) stub_true_ul(X) +#define arch_crashkernel_mem_size() stub_false() +#endif /* ia64 */ + +#ifdef __sparc64__ /* sparc64 */ +int get_versiondep_info_sparc64(void); +int get_phys_base_sparc64(void); +unsigned long long vaddr_to_paddr_sparc64(unsigned long vaddr); +#define find_vmemmap() stub_false() +#define get_machdep_info() TRUE +#define get_phys_base() get_phys_base_sparc64() +#define get_versiondep_info() get_versiondep_info_sparc64() +#define vaddr_to_paddr(X) vaddr_to_paddr_sparc64(X) +#define is_phys_addr(X) stub_true_ul(X) +#define arch_crashkernel_mem_size() stub_false() +#endif /* sparc64 */ + +typedef unsigned long long mdf_pfn_t; + +#ifndef ARCH_PFN_OFFSET +#define ARCH_PFN_OFFSET 0 +#endif +#define paddr_to_pfn(X) \ + (((unsigned long long)(X) >> PAGESHIFT()) - ARCH_PFN_OFFSET) +#define pfn_to_paddr(X) \ + (((mdf_pfn_t)(X) + ARCH_PFN_OFFSET) << PAGESHIFT()) + +/* Format of Xen crash info ELF note */ +typedef struct { + unsigned long xen_major_version; + unsigned long xen_minor_version; + unsigned long xen_extra_version; + unsigned long xen_changeset; + unsigned long xen_compiler; + unsigned long xen_compile_date; + unsigned long xen_compile_time; + unsigned long tainted; +} xen_crash_info_com_t; + +typedef struct { + xen_crash_info_com_t com; +#if defined(__x86__) || defined(__x86_64__) + /* added by changeset 2b43fb3afb3e: */ + unsigned long dom0_pfn_to_mfn_frame_list_list; +#endif +#if defined(__ia64__) + /* added by changeset d7c3b12014b3: */ + unsigned long dom0_mm_pgd_mfn; +#endif +} xen_crash_info_t; + +/* changeset 439a3e9459f2 added xen_phys_start + * to the middle of the struct... */ +typedef struct { + xen_crash_info_com_t com; +#if defined(__x86__) || defined(__x86_64__) + unsigned long xen_phys_start; + unsigned long dom0_pfn_to_mfn_frame_list_list; +#endif +#if defined(__ia64__) + unsigned long dom0_mm_pgd_mfn; +#endif +} xen_crash_info_v2_t; + +struct mem_map_data { + mdf_pfn_t pfn_start; + mdf_pfn_t pfn_end; + unsigned long mem_map; +}; + +struct dump_bitmap { + int fd; + int no_block; + char *file_name; + char *buf; + off_t offset; +}; + +struct cache_data { + int fd; + char *file_name; + char *buf; + size_t buf_size; + size_t cache_size; + off_t offset; +}; +typedef unsigned long int ulong; +typedef unsigned long long int ulonglong; + +/* + * for parallel process + */ + +#define PAGE_FLAG_NUM (20) +#define PAGE_DATA_NUM (5) +#define WAIT_TIME (60 * 10) +#define PTHREAD_FAIL ((void *)-2) +#define THREAD_REGION (200 * 1024) + +struct mmap_cache { + char *mmap_buf; + off_t mmap_start_offset; + off_t mmap_end_offset; +}; + +enum { + FLAG_UNUSED, + FLAG_READY, + FLAG_FILLING +}; +struct page_flag { + mdf_pfn_t pfn; + char zero; + char ready; + short index; + struct page_flag *next; +}; + +struct page_data +{ + long size; + unsigned char *buf; + int flags; + int used; +}; + +struct thread_args { + int thread_num; + unsigned long len_buf_out; + struct cycle *cycle; + struct page_data *page_data_buf; + struct page_flag *page_flag_buf; +}; + +/* + * makedumpfile header + * For re-arranging the dump data on different architecture, all the + * variables are defined by 64bits. The size of signature is aligned + * to 64bits, and change the values to big endian. + */ +#define MAKEDUMPFILE_SIGNATURE "makedumpfile" +#define NUM_SIG_MDF (sizeof(MAKEDUMPFILE_SIGNATURE) - 1) +#define SIZE_SIG_MDF roundup(sizeof(char) * NUM_SIG_MDF, 8) +#define SIG_LEN_MDF (SIZE_SIG_MDF / sizeof(char)) +#define MAX_SIZE_MDF_HEADER (4096) /* max size of makedumpfile_header */ +#define TYPE_FLAT_HEADER (1) /* type of flattened format */ +#define VERSION_FLAT_HEADER (1) /* current version of flattened format */ +#define END_FLAG_FLAT_HEADER (-1) + +struct makedumpfile_header { + char signature[SIG_LEN_MDF]; /* = "makedumpfile" */ + int64_t type; + int64_t version; +}; + +struct makedumpfile_data_header { + int64_t offset; + int64_t buf_size; +}; + +struct splitting_info { + char *name_dumpfile; + int fd_bitmap; + mdf_pfn_t start_pfn; + mdf_pfn_t end_pfn; + off_t offset_eraseinfo; + unsigned long size_eraseinfo; +} splitting_info_t; + +struct parallel_info { + int fd_memory; + int fd_bitmap_memory; + int fd_bitmap; + unsigned char *buf; + unsigned char *buf_out; + struct mmap_cache *mmap_cache; + z_stream zlib_stream; +#ifdef USELZO + lzo_bytep wrkmem; +#endif +} parallel_info_t; + +struct ppc64_vmemmap { + unsigned long phys; + unsigned long virt; +}; + +struct DumpInfo { + int32_t kernel_version; /* version of first kernel*/ + struct timeval timestamp; + struct utsname system_utsname; + + /* + * General info: + */ + int dump_level; /* current dump level */ + int max_dump_level; /* maximum dump level */ + int num_dump_level; /* number of dump level */ + int array_dump_level[NUM_ARRAY_DUMP_LEVEL]; + int flag_compress; /* flag of compression */ + int flag_lzo_support; /* flag of LZO compression support */ + int flag_elf_dumpfile; /* flag of creating ELF dumpfile */ + int flag_generate_vmcoreinfo;/* flag of generating vmcoreinfo file */ + int flag_read_vmcoreinfo; /* flag of reading vmcoreinfo file */ + int flag_show_usage; /* flag of showing usage */ + int flag_show_version; /* flag of showing version */ + int flag_flatten; /* flag of outputting flattened + format to a standard out */ + int flag_rearrange; /* flag of creating dumpfile from + flattened format */ + int flag_split; /* splitting vmcore */ + int flag_cyclic; /* multi-cycle processing is necessary */ + int flag_usemmap; /* /proc/vmcore supports mmap(2) */ + int flag_reassemble; /* reassemble multiple dumpfiles into one */ + int flag_refiltering; /* refilter from kdump-compressed file */ + int flag_force; /* overwrite existing stuff */ + int flag_exclude_xen_dom;/* exclude Domain-U from xen-kdump */ + int flag_dmesg; /* dump the dmesg log out of the vmcore file */ + int flag_partial_dmesg; /* dmesg dump only from the last cleared index*/ + int flag_mem_usage; /*show the page number of memory in different use*/ + int flag_use_printk_log; /* did we read printk_log symbol name? */ + int flag_nospace; /* the flag of "No space on device" error */ + int flag_vmemmap; /* kernel supports vmemmap address space */ + int flag_excludevm; /* -e - excluding unused vmemmap pages */ + int flag_use_count; /* _refcount is named _count in struct page */ + unsigned long vaddr_for_vtop; /* virtual address for debugging */ + long page_size; /* size of page */ + long page_shift; + mdf_pfn_t max_mapnr; /* number of page descriptor */ + unsigned long page_offset; + unsigned long section_size_bits; + unsigned long max_physmem_bits; + unsigned long sections_per_root; + unsigned long phys_base; + unsigned long kernel_start; + unsigned long vmalloc_start; + unsigned long vmalloc_end; + unsigned long vmemmap_start; + unsigned long vmemmap_end; + int vmemmap_psize; + int vmemmap_cnt; + struct ppc64_vmemmap *vmemmap_list; + unsigned long kaslr_offset; + + /* + * page table info for ppc64 + */ + int cur_mmu_type; + int ptrs_per_pgd; + uint l4_index_size; + uint l3_index_size; + uint l2_index_size; + uint l1_index_size; + uint ptrs_per_l4; + uint ptrs_per_l3; + uint ptrs_per_l2; + uint ptrs_per_l1; + uint l4_shift; + uint l3_shift; + uint l2_shift; + uint l1_shift; + uint pte_rpn_shift; + ulong pte_rpn_mask; + ulong pgd_masked_bits; + ulong pud_masked_bits; + ulong pmd_masked_bits; + ulong kernel_pgd; + char *page_buf; /* Page buffer to read page tables */ + + /* + * Filter config file containing filter commands to filter out kernel + * data from vmcore. + */ + char *name_filterconfig; + FILE *file_filterconfig; + + /* + * Filter config file containing eppic language filtering rules + * to filter out kernel data from vmcore + */ + char *name_eppic_config; + + /* + * diskdimp info: + */ + int block_order; + off_t offset_bitmap1; + unsigned long len_bitmap; /* size of bitmap(1st and 2nd) */ + struct dump_bitmap *bitmap1; + struct dump_bitmap *bitmap2; + struct disk_dump_header *dump_header; + struct kdump_sub_header sub_header; + + /* + * ELF header info: + */ + unsigned int num_load_dumpfile; + size_t offset_load_dumpfile; + + /* + * mem_map info: + */ + unsigned int num_mem_map; + struct mem_map_data *mem_map_data; + + int fd_vmlinux; + char *name_vmlinux; + + int fd_xen_syms; + char *name_xen_syms; + + /* + * Dump memory image info: + */ + int fd_memory; + char *name_memory; + struct disk_dump_header *dh_memory; + struct kdump_sub_header *kh_memory; + struct dump_bitmap *bitmap_memory; + unsigned long *valid_pages; + + /* + * Dump file info: + */ + int fd_dumpfile; + char *name_dumpfile; + int num_dumpfile; + struct splitting_info *splitting_info; + struct parallel_info *parallel_info; + + /* + * bitmap info: + */ + int fd_bitmap; + char *name_bitmap; + + /* + * vmcoreinfo file info: + */ + FILE *file_vmcoreinfo; + char *name_vmcoreinfo; /* vmcoreinfo file */ + char release[STRLEN_OSRELEASE]; + int read_text_vmcoreinfo; + + /* + * ELF NOTE section in dump memory image info: + */ + off_t offset_note_dumpfile; + + /* + * erased information in dump memory image info: + */ + unsigned long size_elf_eraseinfo; + + /* + * for Xen extraction + */ + union { /* Both versions of Xen crash info: */ + xen_crash_info_com_t *com; /* common fields */ + xen_crash_info_t *v1; /* without xen_phys_start */ + xen_crash_info_v2_t *v2; /* changeset 439a3e9459f2 */ + } xen_crash_info; + int xen_crash_info_v; /* Xen crash info version: + * 0 .. xen_crash_info_com_t + * 1 .. xen_crash_info_t + * 2 .. xen_crash_info_v2_t */ + + mdf_pfn_t dom0_mapnr; /* The number of page in domain-0. + * Different from max_mapnr. + * max_mapnr is the number of page + * in system. */ + unsigned long xen_phys_start; + unsigned long xen_heap_start; /* start mfn of xen heap area */ + unsigned long xen_heap_end; /* end mfn(+1) of xen heap area */ + unsigned long frame_table_vaddr; + unsigned long max_page; + unsigned long alloc_bitmap; + unsigned long dom0; + unsigned long p2m_frames; + unsigned long *p2m_mfn_frame_list; + int num_domain; + struct domain_list *domain_list; +#if defined(__x86_64__) + unsigned long xen_virt_start; + unsigned long directmap_virt_end; +#endif + + /* + * for splitting + */ + mdf_pfn_t split_start_pfn; + mdf_pfn_t split_end_pfn; + + /* + * for cyclic processing + */ + char *working_dir; /* working directory for bitmap */ + mdf_pfn_t num_dumpable; + unsigned long bufsize_cyclic; + unsigned long pfn_cyclic; + + /* + * for mmap + */ + char *mmap_buf; + off_t mmap_start_offset; + off_t mmap_end_offset; + off_t mmap_region_size; + + /* + * sadump info: + */ + int flag_sadump_diskset; + enum sadump_format_type flag_sadump; /* sadump format type */ + /* + * for filtering free pages managed by buddy system: + */ + int (*page_is_buddy)(unsigned long flags, unsigned int _mapcount, + unsigned long private, unsigned int _count); + /* + * for cyclic_splitting mode, setup splitblock_size + */ + long long splitblock_size; + /* + * for parallel process + */ + int num_threads; + int num_buffers; + pthread_t **threads; + struct thread_args *kdump_thread_args; + struct page_data *page_data_buf; + struct page_flag **page_flag_buf; + sem_t page_flag_buf_sem; + pthread_rwlock_t usemmap_rwlock; + mdf_pfn_t current_pfn; + pthread_mutex_t current_pfn_mutex; + pthread_mutex_t page_data_mutex; + pthread_mutex_t filter_mutex; +}; +extern struct DumpInfo *info; + +/* + * for cyclic_splitting mode,Manage memory by splitblock + */ +#define DEFAULT_SPLITBLOCK_SIZE (1LL << 30) + +struct SplitBlock { + char *table; + long long num; + long long page_per_splitblock; + int entry_size; /* counted by byte */ +}; + +/* + * kernel VM-related data + */ +struct vm_table { + int numnodes; + unsigned long *node_online_map; + int node_online_map_len; + unsigned int mem_flags; +}; +extern struct vm_table vt; + +/* + * Loaded module symbols info. + */ +#define MOD_NAME_LEN 64 +#define IN_RANGE(addr, mbase, sz) \ + (((unsigned long)(addr) >= (unsigned long)mbase) \ + && ((unsigned long)addr < (unsigned long)(mbase + sz))) + +struct symbol_info { + char *name; + unsigned long long value; +}; + +struct module_info { + char name[MOD_NAME_LEN]; + unsigned int num_syms; + struct symbol_info *sym_info; +}; + + +struct symbol_table { + unsigned long long mem_map; + unsigned long long vmem_map; + unsigned long long mem_section; + unsigned long long pkmap_count; + unsigned long long pkmap_count_next; + unsigned long long system_utsname; + unsigned long long init_uts_ns; + unsigned long long _stext; + unsigned long long swapper_pg_dir; + unsigned long long init_level4_pgt; + unsigned long long level4_kernel_pgt; + unsigned long long init_top_pgt; + unsigned long long vmlist; + unsigned long long vmap_area_list; + unsigned long long phys_base; + unsigned long long node_online_map; + unsigned long long node_states; + unsigned long long node_memblk; + unsigned long long node_data; + unsigned long long pgdat_list; + unsigned long long contig_page_data; + unsigned long long log_buf; + unsigned long long log_buf_len; + unsigned long long log_end; + unsigned long long log_first_idx; + unsigned long long clear_idx; + unsigned long long log_next_idx; + unsigned long long max_pfn; + unsigned long long node_remap_start_vaddr; + unsigned long long node_remap_end_vaddr; + unsigned long long node_remap_start_pfn; + unsigned long long free_huge_page; + + /* + * for Xen extraction + */ + unsigned long long dom_xen; + unsigned long long dom_io; + unsigned long long domain_list; + unsigned long long frame_table; + unsigned long long xen_heap_start; + unsigned long long pgd_l2; + unsigned long long pgd_l3; + unsigned long long pgd_l4; + unsigned long long xenheap_phys_end; + unsigned long long xen_pstart; + unsigned long long frametable_pg_dir; + unsigned long long max_page; + unsigned long long alloc_bitmap; + + /* + * for loading module symbol data + */ + + unsigned long long modules; + + /* + * vmalloc_start address on s390x arch + */ + unsigned long long high_memory; + + /* + * for sadump + */ + unsigned long long linux_banner; + unsigned long long bios_cpu_apicid; + unsigned long long x86_bios_cpu_apicid; + unsigned long long x86_bios_cpu_apicid_early_ptr; + unsigned long long x86_bios_cpu_apicid_early_map; + unsigned long long crash_notes; + unsigned long long __per_cpu_offset; + unsigned long long __per_cpu_load; + unsigned long long cpu_online_mask; + unsigned long long __cpu_online_mask; + unsigned long long kexec_crash_image; + unsigned long long divide_error; + unsigned long long idt_table; + unsigned long long saved_command_line; + unsigned long long pti_init; + unsigned long long kaiser_init; + + /* + * symbols on ppc64 arch + */ + unsigned long long vmemmap_list; + unsigned long long mmu_vmemmap_psize; + unsigned long long mmu_psize_defs; + unsigned long long cpu_pgd; + unsigned long long demote_segment_4k; + unsigned long long cur_cpu_spec; + + /* + * symbols on sparc64 arch + */ + unsigned long long vmemmap_table; +}; + +struct size_table { + long page; + long mem_section; + long pglist_data; + long zone; + long free_area; + long list_head; + long node_memblk_s; + long nodemask_t; + long printk_log; + + /* + * for Xen extraction + */ + long page_info; + long domain; + + /* + * for loading module symbol data + */ + long module; + + /* + * for sadump + */ + long percpu_data; + long elf_prstatus; + long user_regs_struct; + long cpumask; + long cpumask_t; + long kexec_segment; + long elf64_hdr; + + /* + * symbols on ppc64 arch + */ + long vmemmap_backing; + long mmu_psize_def; + long cpu_spec; + + long pageflags; +}; + +struct offset_table { + struct page { + long flags; + long _refcount; + long mapping; + long lru; + long _mapcount; + long private; + long compound_dtor; + long compound_order; + long compound_head; + } page; + struct mem_section { + long section_mem_map; + } mem_section; + struct zone { + long free_pages; + long free_area; + long vm_stat; + long spanned_pages; + } zone; + struct pglist_data { + long node_zones; + long nr_zones; + long node_mem_map; + long node_start_pfn; + long node_spanned_pages; + long pgdat_next; + } pglist_data; + struct free_area { + long free_list; + } free_area; + struct list_head { + long next; + long prev; + } list_head; + struct node_memblk_s { + long start_paddr; + long size; + long nid; + } node_memblk_s; + struct vm_struct { + long addr; + } vm_struct; + struct vmap_area { + long va_start; + long list; + } vmap_area; + + /* + * for Xen extraction + */ + struct page_info { + long count_info; + long _domain; + } page_info; + struct domain { + long domain_id; + long next_in_list; + } domain; + + /* + * for loading module symbol data + */ + struct module { + long list; + long name; + long module_core; + long core_size; + long module_init; + long init_size; + long num_symtab; + long symtab; + long strtab; + } module; + + /* + * for loading elf_prstaus symbol data + */ + struct elf_prstatus_s { + long pr_reg; + } elf_prstatus; + + /* + * for loading user_regs_struct symbol data + */ + struct user_regs_struct_s { + long r15; + long r14; + long r13; + long r12; + long bp; + long bx; + long r11; + long r10; + long r9; + long r8; + long ax; + long cx; + long dx; + long si; + long di; + long orig_ax; + long ip; + long cs; + long flags; + long sp; + long ss; + long fs_base; + long gs_base; + long ds; + long es; + long fs; + long gs; + } user_regs_struct; + + struct kimage_s { + long segment; + } kimage; + + struct kexec_segment_s { + long mem; + } kexec_segment; + + struct elf64_hdr_s { + long e_phnum; + long e_phentsize; + long e_phoff; + } elf64_hdr; + + struct elf64_phdr_s { + long p_type; + long p_offset; + long p_paddr; + long p_memsz; + } elf64_phdr; + + struct printk_log_s { + long ts_nsec; + long len; + long text_len; + } printk_log; + + /* + * symbols on ppc64 arch + */ + struct mmu_psize_def_s { + long shift; + } mmu_psize_def; + + struct vmemmap_backing_s { + long phys; + long virt_addr; + long list; + } vmemmap_backing; + + struct cpu_spec_s { + long mmu_features; + } cpu_spec; +}; + +/* + * The number of array + */ +struct array_table { + /* + * Symbol + */ + long node_data; + long pgdat_list; + long mem_section; + long node_memblk; + long __per_cpu_offset; + long node_remap_start_pfn; + + /* + * Structure + */ + struct zone_at { + long free_area; + } zone; + struct free_area_at { + long free_list; + } free_area; + struct kimage_at { + long segment; + } kimage; +}; + +struct number_table { + long NR_FREE_PAGES; + long N_ONLINE; + long pgtable_l5_enabled; + + /* + * Page flags + */ + long PG_lru; + long PG_private; + long PG_head; + long PG_head_mask; + long PG_swapcache; + long PG_swapbacked; + long PG_buddy; + long PG_slab; + long PG_hwpoison; + + long PAGE_BUDDY_MAPCOUNT_VALUE; + long SECTION_SIZE_BITS; + long MAX_PHYSMEM_BITS; + long HUGETLB_PAGE_DTOR; + long phys_base; +#ifdef __aarch64__ + long VA_BITS; + unsigned long PHYS_OFFSET; + unsigned long kimage_voffset; +#endif +}; + +struct srcfile_table { + /* + * typedef + */ + char pud_t[LEN_SRCFILE]; +}; + +/* + * This structure records where the vmemmap page structures reside, and which + * pfn's are represented by those page structures. + * The actual pages containing the page structures are 2MB pages, so their pfn's + * will all be multiples of 0x200. + * The page structures are 7 64-bit words in length (0x38) so they overlap the + * 2MB boundaries. Each page structure represents a 4k page. + * A 4k page is here defined to be represented on a 2MB page if its page structure + * 'ends' on that page (even if it began on the page before). + */ +struct vmap_pfns { + struct vmap_pfns *next; + struct vmap_pfns *prev; + /* + * These (start/end) are literal pfns of 2MB pages on which the page + * structures reside, not start and end+1. + */ + unsigned long vmap_pfn_start; + unsigned long vmap_pfn_end; + /* + * These (start/end) are literal pfns represented on these pages, not + * start and end+1. + * The starting page struct is at least partly on the first page; the + * ending page struct is entirely on the last page. + */ + unsigned long rep_pfn_start; + unsigned long rep_pfn_end; +}; + +/* for saving a list of pfns to a buffer, and then to a file if necessary */ +struct save_control { + int sc_fd; + char *sc_filename; + char *sc_buf; + long sc_buflen; /* length of buffer never changes */ + long sc_bufposition; /* offset of next slot for write, or next to be read */ + long sc_filelen; /* length of valid data written */ + long sc_fileposition; /* offset in file of next entry to be read */ +}; +/* one entry in the buffer and file */ +struct sc_entry { + unsigned long startpfn; + unsigned long numpfns; +}; + +extern struct symbol_table symbol_table; +extern struct size_table size_table; +extern struct offset_table offset_table; +extern struct array_table array_table; +extern struct number_table number_table; +extern struct srcfile_table srcfile_table; + +struct memory_range { + unsigned long long start, end; +}; + +#define CRASH_RESERVED_MEM_NR 8 +struct memory_range crash_reserved_mem[CRASH_RESERVED_MEM_NR]; +int crash_reserved_mem_nr; + +unsigned long read_vmcoreinfo_symbol(char *str_symbol); +int readmem(int type_addr, unsigned long long addr, void *bufptr, size_t size); +int get_str_osrelease_from_vmlinux(void); +int read_vmcoreinfo_xen(void); +int exclude_xen_user_domain(void); +mdf_pfn_t get_num_dumpable(void); +int __read_disk_dump_header(struct disk_dump_header *dh, char *filename); +int read_disk_dump_header(struct disk_dump_header *dh, char *filename); +int read_kdump_sub_header(struct kdump_sub_header *kh, char *filename); +void close_vmcoreinfo(void); +int close_files_for_creating_dumpfile(void); +int iomem_for_each_line(char *match, int (*callback)(void *data, int nr, + char *str, + unsigned long base, + unsigned long length), + void *data); +int is_bigendian(void); +int get_symbol_info(void); + +/* + * for Xen extraction + */ +struct domain_list { + unsigned long domain_addr; + unsigned int domain_id; + unsigned int pickled_id; +}; + +#define PAGES_PER_MAPWORD (sizeof(unsigned long) * 8) +#define MFNS_PER_FRAME (info->page_size / sizeof(unsigned long)) + +#ifdef __aarch64__ +unsigned long long kvtop_xen_arm64(unsigned long kvaddr); +#define kvtop_xen(X) kvtop_xen_arm64(X) +#endif /* aarch64 */ + +#ifdef __arm__ +#define kvtop_xen(X) FALSE +#define get_xen_basic_info_arch(X) FALSE +#define get_xen_info_arch(X) FALSE +#endif /* arm */ + +#ifdef __x86__ +#define HYPERVISOR_VIRT_START_PAE (0xF5800000UL) +#define HYPERVISOR_VIRT_START (0xFC000000UL) +#define HYPERVISOR_VIRT_END (0xFFFFFFFFUL) +#define DIRECTMAP_VIRT_START (0xFF000000UL) +#define DIRECTMAP_VIRT_END (0xFFC00000UL) +#define FRAMETABLE_VIRT_START (0xF6800000UL) + +#define is_xen_vaddr(x) \ + ((x) >= HYPERVISOR_VIRT_START_PAE && (x) < HYPERVISOR_VIRT_END) +#define is_direct(x) \ + ((x) >= DIRECTMAP_VIRT_START && (x) < DIRECTMAP_VIRT_END) + +unsigned long long kvtop_xen_x86(unsigned long kvaddr); +#define kvtop_xen(X) kvtop_xen_x86(X) + +int get_xen_basic_info_x86(void); +#define get_xen_basic_info_arch(X) get_xen_basic_info_x86(X) +int get_xen_info_x86(void); +#define get_xen_info_arch(X) get_xen_info_x86(X) + +#endif /* __x86__ */ + +#ifdef __x86_64__ + +/* The architectural limit for physical addresses is 52 bits. + * Mask off bits 52-62 (available for OS use) and bit 63 (NX). + */ +#define ENTRY_MASK (~0xfff0000000000fffULL) +#define MAX_X86_64_FRAMES (info->page_size / sizeof(unsigned long)) + +#define PAGE_OFFSET_XEN_DOM0 (0xffff880000000000) /* different from linux */ +#define HYPERVISOR_VIRT_START (0xffff800000000000) +#define HYPERVISOR_VIRT_END (0xffff880000000000) +#define DIRECTMAP_VIRT_START (0xffff830000000000) +#define DIRECTMAP_VIRT_END_V3 (0xffff840000000000) +#define DIRECTMAP_VIRT_END_V4 (0xffff880000000000) +#define DIRECTMAP_VIRT_END (info->directmap_virt_end) +#define XEN_VIRT_START (info->xen_virt_start) +#define XEN_VIRT_END (XEN_VIRT_START + (1UL << 30)) +#define FRAMETABLE_VIRT_START_V3 0xffff82f600000000 +#define FRAMETABLE_VIRT_START_V4_3 0xffff82e000000000 + +#define is_xen_vaddr(x) \ + ((x) >= HYPERVISOR_VIRT_START && (x) < HYPERVISOR_VIRT_END) +#define is_direct(x) \ + ((x) >= DIRECTMAP_VIRT_START && (x) < DIRECTMAP_VIRT_END) +#define is_xen_text(x) \ + ((x) >= XEN_VIRT_START && (x) < XEN_VIRT_END) + +unsigned long long kvtop_xen_x86_64(unsigned long kvaddr); +#define kvtop_xen(X) kvtop_xen_x86_64(X) + +int get_xen_basic_info_x86_64(void); +#define get_xen_basic_info_arch(X) get_xen_basic_info_x86_64(X) +int get_xen_info_x86_64(void); +#define get_xen_info_arch(X) get_xen_info_x86_64(X) + +#endif /* __x86_64__ */ + +#ifdef __ia64__ +#define HYPERVISOR_VIRT_START (0xe800000000000000) +#define HYPERVISOR_VIRT_END (0xf800000000000000) +#define DEFAULT_SHAREDINFO_ADDR (0xf100000000000000) +#define PERCPU_PAGE_SIZE 65536 +#define PERCPU_ADDR (DEFAULT_SHAREDINFO_ADDR - PERCPU_PAGE_SIZE) +#define DIRECTMAP_VIRT_START (0xf000000000000000) +#define DIRECTMAP_VIRT_END PERCPU_ADDR +#define VIRT_FRAME_TABLE_ADDR (0xf300000000000000) +#define VIRT_FRAME_TABLE_END (0xf400000000000000) + +#define is_xen_vaddr(x) \ + ((x) >= HYPERVISOR_VIRT_START && (x) < HYPERVISOR_VIRT_END) +#define is_direct(x) \ + ((x) >= DIRECTMAP_VIRT_START && (x) < DIRECTMAP_VIRT_END) +#define is_frame_table_vaddr(x) \ + ((x) >= VIRT_FRAME_TABLE_ADDR && (x) < VIRT_FRAME_TABLE_END) + +#define PGDIR_SHIFT (PAGESHIFT() + 2 * (PAGESHIFT() - 3)) +#define PTRS_PER_PGD (1UL << (PAGESHIFT() - 3)) +#define PTRS_PER_PMD (1UL << (PAGESHIFT() - 3)) +#define PTRS_PER_PTE (1UL << (PAGESHIFT() - 3)) + +#define IA64_MAX_PHYS_BITS 50 +#define _PAGE_P (1) +#define _PFN_MASK (((1UL << IA64_MAX_PHYS_BITS) - 1) & ~0xfffUL) + +unsigned long long kvtop_xen_ia64(unsigned long kvaddr); +#define kvtop_xen(X) kvtop_xen_ia64(X) + +int get_xen_basic_info_ia64(void); +#define get_xen_basic_info_arch(X) get_xen_basic_info_ia64(X) +int get_xen_info_ia64(void); +#define get_xen_info_arch(X) get_xen_info_ia64(X) + +#endif /* __ia64 */ + +#if defined(__powerpc64__) || defined(__powerpc32__) /* powerpcXX */ +#define kvtop_xen(X) FALSE +#define get_xen_basic_info_arch(X) FALSE +#define get_xen_info_arch(X) FALSE +#endif /* powerpcXX */ + +#ifdef __s390x__ /* s390x */ +#define kvtop_xen(X) FALSE +#define get_xen_basic_info_arch(X) FALSE +#define get_xen_info_arch(X) FALSE +#endif /* s390x */ + +#ifdef __sparc64__ /* sparc64 */ +#define kvtop_xen(X) FALSE +#define get_xen_basic_info_arch(X) FALSE +#define get_xen_info_arch(X) FALSE +#endif /* sparc64 */ + +struct cycle { + mdf_pfn_t start_pfn; + mdf_pfn_t end_pfn; + + /* for excluding multi-page regions */ + mdf_pfn_t exclude_pfn_start; + mdf_pfn_t exclude_pfn_end; + mdf_pfn_t *exclude_pfn_counter; +}; + +static inline int +is_on(char *bitmap, mdf_pfn_t i) +{ + return bitmap[i>>3] & (1 << (i & 7)); +} + +static inline int +is_cyclic_region(mdf_pfn_t pfn, struct cycle *cycle) +{ + if (pfn < cycle->start_pfn || cycle->end_pfn <= pfn) + return FALSE; + else + return TRUE; +} + +static inline int +is_dumpable_buffer(struct dump_bitmap *bitmap, mdf_pfn_t pfn, struct cycle *cycle) +{ + if (!is_cyclic_region(pfn, cycle)) + return FALSE; + else + return is_on(bitmap->buf, pfn - cycle->start_pfn); +} + +static inline int +is_dumpable_file(struct dump_bitmap *bitmap, mdf_pfn_t pfn) +{ + off_t offset; + ssize_t rcode; + if (pfn == 0 || bitmap->no_block != pfn/PFN_BUFBITMAP) { + offset = bitmap->offset + BUFSIZE_BITMAP*(pfn/PFN_BUFBITMAP); + if (lseek(bitmap->fd, offset, SEEK_SET) < 0 ) { + ERRMSG("Can't seek the bitmap(%s). %s\n", + bitmap->file_name, strerror(errno)); + return FALSE; + } + + rcode = read(bitmap->fd, bitmap->buf, BUFSIZE_BITMAP); + if (rcode != BUFSIZE_BITMAP) + ERRMSG("Can't read the bitmap(%s). %s\n", + bitmap->file_name, strerror(errno)); + if (pfn == 0) + bitmap->no_block = 0; + else + bitmap->no_block = pfn/PFN_BUFBITMAP; + } + return is_on(bitmap->buf, pfn%PFN_BUFBITMAP); +} + +static inline int +is_dumpable(struct dump_bitmap *bitmap, mdf_pfn_t pfn, struct cycle *cycle) +{ + if (bitmap->fd < 0) { + return is_dumpable_buffer(bitmap, pfn, cycle); + } else { + return is_dumpable_file(bitmap, pfn); + } +} + +static inline int +is_zero_page(unsigned char *buf, long page_size) +{ + size_t i; + unsigned long long *vect = (unsigned long long *) buf; + long page_len = page_size / sizeof(unsigned long long); + + for (i = 0; i < page_len; i++) + if (vect[i]) + return FALSE; + return TRUE; +} + +void write_vmcoreinfo_data(void); +int set_bit_on_1st_bitmap(mdf_pfn_t pfn, struct cycle *cycle); +int clear_bit_on_1st_bitmap(mdf_pfn_t pfn, struct cycle *cycle); + +#ifdef __x86__ + +struct user_regs_struct { + unsigned long bx; + unsigned long cx; + unsigned long dx; + unsigned long si; + unsigned long di; + unsigned long bp; + unsigned long ax; + unsigned long ds; + unsigned long es; + unsigned long fs; + unsigned long gs; + unsigned long orig_ax; + unsigned long ip; + unsigned long cs; + unsigned long flags; + unsigned long sp; + unsigned long ss; +}; + +struct elf_prstatus { + char pad1[72]; + struct user_regs_struct pr_reg; + char pad2[4]; +}; + +#endif + +#ifdef __x86_64__ + +struct user_regs_struct { + unsigned long r15; + unsigned long r14; + unsigned long r13; + unsigned long r12; + unsigned long bp; + unsigned long bx; + unsigned long r11; + unsigned long r10; + unsigned long r9; + unsigned long r8; + unsigned long ax; + unsigned long cx; + unsigned long dx; + unsigned long si; + unsigned long di; + unsigned long orig_ax; + unsigned long ip; + unsigned long cs; + unsigned long flags; + unsigned long sp; + unsigned long ss; + unsigned long fs_base; + unsigned long gs_base; + unsigned long ds; + unsigned long es; + unsigned long fs; + unsigned long gs; +}; + +struct elf_prstatus { + char pad1[112]; + struct user_regs_struct pr_reg; + char pad2[4]; +}; + +#endif + +/* + * Below are options which getopt_long can recognize. From OPT_START options are + * non-printable, just used for implementation. + */ +#define OPT_BLOCK_ORDER 'b' +#define OPT_COMPRESS_ZLIB 'c' +#define OPT_DEBUG 'D' +#define OPT_DUMP_LEVEL 'd' +#define OPT_ELF_DUMPFILE 'E' +#define OPT_EXCLUDE_UNUSED_VM 'e' +#define OPT_FLATTEN 'F' +#define OPT_FORCE 'f' +#define OPT_GENERATE_VMCOREINFO 'g' +#define OPT_HELP 'h' +#define OPT_READ_VMCOREINFO 'i' +#define OPT_COMPRESS_LZO 'l' +#define OPT_COMPRESS_SNAPPY 'p' +#define OPT_REARRANGE 'R' +#define OPT_VERSION 'v' +#define OPT_EXCLUDE_XEN_DOM 'X' +#define OPT_VMLINUX 'x' +#define OPT_START 256 +#define OPT_SPLIT OPT_START+0 +#define OPT_REASSEMBLE OPT_START+1 +#define OPT_XEN_SYMS OPT_START+2 +#define OPT_XEN_VMCOREINFO OPT_START+3 +#define OPT_XEN_PHYS_START OPT_START+4 +#define OPT_MESSAGE_LEVEL OPT_START+5 +#define OPT_VTOP OPT_START+6 +#define OPT_DUMP_DMESG OPT_START+7 +#define OPT_CONFIG OPT_START+8 +#define OPT_DISKSET OPT_START+9 +#define OPT_CYCLIC_BUFFER OPT_START+10 +#define OPT_EPPIC OPT_START+11 +#define OPT_NON_MMAP OPT_START+12 +#define OPT_MEM_USAGE OPT_START+13 +#define OPT_SPLITBLOCK_SIZE OPT_START+14 +#define OPT_WORKING_DIR OPT_START+15 +#define OPT_NUM_THREADS OPT_START+16 +#define OPT_PARTIAL_DMESG OPT_START+17 + +/* + * Function Prototype. + */ +mdf_pfn_t get_num_dumpable_cyclic(void); +mdf_pfn_t get_num_dumpable_cyclic_withsplit(void); +int get_loads_dumpfile_cyclic(void); +int initial_xen(void); +unsigned long long ptom_xen(unsigned long long paddr); +unsigned long long get_free_memory_size(void); +int calculate_cyclic_buffer_size(void); +int prepare_splitblock_table(void); +int initialize_zlib(z_stream *stream, int level); +int finalize_zlib(z_stream *stream); + +int parse_line(char *str, char *argv[]); +char *shift_string_left(char *s, int cnt); +char *clean_line(char *line); +char *strip_linefeeds(char *line); +char *strip_beginning_whitespace(char *line); +char *strip_ending_whitespace(char *line); +ulong htol(char *s, int flags); +int hexadecimal(char *s, int count); +int decimal(char *s, int count); +int file_exists(char *file); + +#endif /* MAKEDUMPFILE_H */ |