You can subscribe to this list here.
2005 |
Jan
|
Feb
|
Mar
|
Apr
(147) |
May
(104) |
Jun
(587) |
Jul
(83) |
Aug
(270) |
Sep
(1) |
Oct
(133) |
Nov
(353) |
Dec
(129) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2006 |
Jan
(15) |
Feb
(31) |
Mar
(32) |
Apr
|
May
|
Jun
(2) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(22) |
Dec
|
From: kaku <fk...@us...> - 2006-03-03 07:27:08
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/arch/x86_64/kernel In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12353 Modified Files: machine_mkexec.c Log Message: Delete header asm/mkexec-x86_64.h. Index: machine_mkexec.c =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/arch/x86_64/kernel/machine_mkexec.c,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** machine_mkexec.c 14 Feb 2006 05:50:28 -0000 1.2 --- machine_mkexec.c 3 Mar 2006 07:27:05 -0000 1.3 *************** *** 38,42 **** #include <linux/mkexec.h> - #include <asm/mkexec-x86_64.h> #define LEVEL0_SIZE (1UL << 12UL) --- 38,41 ---- |
From: kaku <fk...@us...> - 2006-03-03 00:17:44
|
Update of /cvsroot/mkdump/utils/mkd_save In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27843 Modified Files: mkd_save Log Message: Changed to use it if there is mkd_conv. Index: mkd_save =================================================================== RCS file: /cvsroot/mkdump/utils/mkd_save/mkd_save,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** mkd_save 9 Feb 2006 03:54:00 -0000 1.7 --- mkd_save 3 Mar 2006 00:17:41 -0000 1.8 *************** *** 27,33 **** --- 27,39 ---- CONFIG_FILE=/etc/mkdump/mkdump MEMDUMP_FILE=mkdump + LKCDDUMP_FILE=lkcd_dump SWAPDUMP_FILE=mkswpdump MKDUMP_LIMIT_DEFAULT=5 BLOCK_SIZE=1M + MKD_CONV="" + which mkd_conv 1> /dev/null 2>&1 + if [ $? -eq 0 ]; then + MKD_CONV=mkd_conv + fi MACHINE=`uname -m` *************** *** 87,91 **** # check dump header #--------------------------------------------------------------- ! CheckDumpHeader `mkd_chk -n $MKDUMP_DEV` if [ $? -ne 0 ]; then echo "skip dump save." --- 93,101 ---- # check dump header #--------------------------------------------------------------- ! if [ -z "$MKD_CONV" ]; then ! CheckDumpHeader `mkd_chk -n $MKDUMP_DEV` ! else ! CheckDumpHeader `$MKD_CONV -I -n $MKDUMP_DEV` ! fi if [ $? -ne 0 ]; then echo "skip dump save." *************** *** 110,117 **** #--------------------------------------------------------------- echo "save mkdump.($MKDUMP_DEV)" ! dd if=$MKDUMP_DEV of=$SAVE_DIR/$MEMDUMP_FILE bs=$BLOCK_SIZE [ $? -ne 0 ] && exit 1 #--------------------------------------------------------------- # save swap dump. #--------------------------------------------------------------- --- 120,142 ---- #--------------------------------------------------------------- echo "save mkdump.($MKDUMP_DEV)" ! if [ -z "$MKD_CONV" ]; then ! dd if=$MKDUMP_DEV of=$SAVE_DIR/$MEMDUMP_FILE bs=$BLOCK_SIZE ! else ! $MKD_CONV $MKDUMP_DEV $SAVE_DIR/$LKCDDUMP_FILE ! fi [ $? -ne 0 ] && exit 1 #--------------------------------------------------------------- + # pre-format dump device. + #--------------------------------------------------------------- + if [ "x${MKDUMP_PREFORMAT}" = "xy" -o "x${MKDUMP_PREFORMAT}" = "xY" ]; then + if [ -n "$MKD_CONV" ]; then + echo "pre-format dump device" + $MKD_CONV -P $MKDUMP_DEV + [ $? -ne 0 ] && exit 1 + fi + fi + + #--------------------------------------------------------------- # save swap dump. #--------------------------------------------------------------- *************** *** 120,124 **** for f in $MKDUMP_SWAPDEV; do echo "save swap device.($f)" ! dd if=$f of=${SAVE_DIR}/${SWAPDUMP_FILE}${i} bs=$BLOCK_SIZE [ $? -ne 0 ] && exit 1 let i=$i+1 --- 145,153 ---- for f in $MKDUMP_SWAPDEV; do echo "save swap device.($f)" ! if [ -z "$MKD_CONV" ]; then ! dd if=$f of=${SAVE_DIR}/${SWAPDUMP_FILE}${i} bs=$BLOCK_SIZE ! else ! $MKD_CONV -d 0 -n $f ${SAVE_DIR}/${SWAPDUMP_FILE}${i} ! fi [ $? -ne 0 ] && exit 1 let i=$i+1 *************** *** 129,133 **** # set unique. #--------------------------------------------------------------- ! mkd_chk -n -w0 $MKDUMP_DEV > /dev/null [ $? -ne 0 ] && exit 1 --- 158,166 ---- # set unique. #--------------------------------------------------------------- ! if [ -z "$MKD_CONV" ]; then ! mkd_chk -n -w0 $MKDUMP_DEV > /dev/null ! else ! $MKD_CONV -n -w0 $MKDUMP_DEV > /dev/null ! fi [ $? -ne 0 ] && exit 1 |
From: kaku <fk...@us...> - 2006-03-03 00:07:53
|
Update of /cvsroot/mkdump/utils In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22352 Modified Files: Makefile Log Message: Added mkd_conv. Index: Makefile =================================================================== RCS file: /cvsroot/mkdump/utils/Makefile,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** Makefile 19 Dec 2005 03:06:24 -0000 1.2 --- Makefile 3 Mar 2006 00:07:46 -0000 1.3 *************** *** 45,48 **** --- 45,49 ---- install: $(INSTALL_CMD) $(MKD_CHK_PATH)/$(MKD_CHK) $(INST_PATH) + $(INSTALL_CMD) $(MKD_CHK_PATH)/$(MKD_CONV) $(INST_PATH) $(INSTALL_CMD) $(MKD_LOAD_PATH)/$(MKD_LOAD) $(INST_PATH) $(INSTALL_CMD) $(MKD_SAVE_PATH)/$(MKD_SAVE) $(INST_PATH) |
From: kaku <fk...@us...> - 2006-03-03 00:02:36
|
Update of /cvsroot/mkdump/utils/mkd_conv In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17398 Modified Files: .cvsignore Log Message: Added mkd_conv. Index: .cvsignore =================================================================== RCS file: /cvsroot/mkdump/utils/mkd_conv/.cvsignore,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** .cvsignore 20 Jun 2005 08:40:20 -0000 1.1 --- .cvsignore 3 Mar 2006 00:02:30 -0000 1.2 *************** *** 3,4 **** --- 3,5 ---- mkd2lkcd_i386 mkd2lkcd_x86_64 + mkd_conv |
From: kaku <fk...@us...> - 2006-03-03 00:00:07
|
Update of /cvsroot/mkdump/utils/mkd_conv In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15375 Added Files: mkd_conv.c mkd_conv.h mkd_conv_lkcd_i386.c mkd_conv_lkcd_x86_64.c Log Message: Added mkd_conv utility. --- NEW FILE: mkd_conv.h --- /* * mkd_conv/mkd_conv.h * * $Id: mkd_conv.h,v 1.1 2006/03/03 00:00:01 fkak Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * 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 (version 2 of the License). * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _MKDC_MKD_CONV_H_ #define _MKDC_MKD_CONV_H_ #include "typedefs.h" #include "./lkcd_dump.h" struct mkd_conv_opts { int f_conv; int f_chk; int f_info; int f_format; int f_direct; int f_force; int f_noverbose; int f_save; int f_writeu; }; typedef struct mkd_conv_opts mkd_conv_opts_t; struct dump_cache { int arch; u32 p_sz; int p_num; size_t buf_sz; u64 blk; int r_dv; int r_dm; int r_dt; struct dump_version *dvp; struct mem_seg *dmp; struct dump_version *dtp; char *buf; }; typedef struct dump_cache dump_cache_t; #define DSP_INDICATOR(total, current, old_per) \ do { \ int cur_per; \ cur_per = current * 100 / total; \ if (cur_per > old_per) { \ fprintf(stderr, "\r%d%%", cur_per); \ fflush(stderr); \ old_per = cur_per; \ } \ } while (0) #ifdef _DEBUG_PRINT #define DPRINT(x) printf x; #else #define DPRINT(x) #endif #define CHECK_HEADER_VERBOSE 1 #define CHECK_HEADER_NOVERBOSE 0 #define COPY_DUMP_CHK 1 #define COPY_DUMP_NOCHK 0 extern void fprintf_verb(int verbose, char *msg); extern int check_header(struct dump_version *dvp, int arch, int verbose); extern int check_memseg(struct mem_seg *dmp, u64 *blk, int verbose); extern int check_tailer(struct dump_version *dvp0, struct dump_version *dvp1, int arch, int verbose); extern int mkd2lkcd_i386(int in_fd, int out_fd, dump_cache_t *dcache, u64 *blk_cnt); extern int mkd2lkcd_x86_64(int in_fd, int out_fd, dump_cache_t *dcache, u64 *blk_cnt); #endif /* _MKDC_MKD_CONV_H_ */ --- NEW FILE: mkd_conv.c --- /* * mkd_conv/mkd_conv.c * * $Id: mkd_conv.c,v 1.1 2006/03/03 00:00:00 fkak Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * 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 (version 2 of the License). * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #define _XOPEN_SOURCE 600 #include <getopt.h> #include <errno.h> #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/utsname.h> #include <stdlib.h> #include <dirent.h> #include "typedefs.h" #include "minik_dump.h" #include "mkd_conv.h" #define EXIT_OK 0 #define EXIT_ERROR 1 #define DUMP_CACHE_NUM 128 #define PAGE_SHIFT 12 #define PAGE_SIZE (1UL << PAGE_SHIFT) char *program_name; static int get_headers(int fd_in, dump_cache_t *dcache, int verbose); static int update_header(int fd, dump_cache_t *dcache, u32 unique, int verbose); static int copy_dump_no_conv(int fd_in, int fd_out, char *file_nm, dump_cache_t *dcache, int chk, u64 *sum); static int check_dump_stat(int fd, dump_cache_t *dcache, u64 *blk); static int format_ddev(int fd, char *file_nm, dump_cache_t *dcache, u64 *sum); static int check_devf(int fd, char *file_nm, u64 *size); void fprintf_verb(int verbose, char *msg); int check_header(struct dump_version *dvp, int arch, int verbose); int check_memseg(struct mem_seg *dmp, u64 *blk, int verbose); int check_tailer(struct dump_version *dvp0, struct dump_version *dvp1, int arch, int verbose); int main(int argc, char *argv[]) { int ret = EXIT_ERROR, result; int res_conv = 0; int res_header = 0; char *file_in = NULL; char *file_out = NULL; int fd_in = -1, fd_out = -1; int opt; int f_direct_chk = COPY_DUMP_CHK; char *endptr = NULL; int open_flags = O_RDONLY, verbose = CHECK_HEADER_VERBOSE; u32 unique; mkd_conv_opts_t opts_f = { .f_conv = 0, .f_chk = 0, .f_info = 0, .f_format = 0, .f_direct = 0, .f_force = 0, .f_noverbose = 0, .f_save = 0, .f_writeu = 0 }; struct utsname utsname; int arch, arch_uname = 0, arch_in = 0; char *buf = NULL; dump_cache_t dcache = { .arch = 0, .p_sz = PAGE_SIZE, .p_num = DUMP_CACHE_NUM, .buf_sz = 0, .blk = 0, .r_dv = -1, .r_dm = -1, .r_dt = -1, .dvp = NULL, .dmp = NULL, .dtp = NULL, .buf = NULL }; int i; u64 f_sum = 0, blk_cnt = 0; int flg_remove = 1; DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); program_name = argv[0]; while ((opt = getopt(argc, argv, "CIPcfnsa:d:w:")) > 0) { switch (opt) { case 'C': opts_f.f_chk = 1; break; case 'I': opts_f.f_info = 1; break; case 'P': opts_f.f_format = 1; open_flags = O_RDWR; break; case 'f': opts_f.f_force = 1; break; case 'n': opts_f.f_noverbose = 1; verbose = CHECK_HEADER_NOVERBOSE; break; case 's': opts_f.f_save = 1; break; case 'a': arch_in = strtoul(optarg, &endptr, 0); if ('\0' != *endptr) { if (errno) { perror("strtoul -a option"); } else { fprintf(stderr, "-a option strtoul error\n"); } goto L_close; } if (arch_in > DUMP_ARCH_IA64 || arch_in < DUMP_ARCH_I386) { fprintf(stderr, "-a invalid architecture.\n"); goto L_close; } break; case 'd': opts_f.f_direct = 1; result = strtoul(optarg, &endptr, 0); if ('\0' != *endptr) { if (errno) { perror("strtoul -d option"); } else { fprintf(stderr, "-d option strtoul error\n"); } goto L_close; } if (result == 0) { f_direct_chk = COPY_DUMP_NOCHK; } else { f_direct_chk = COPY_DUMP_CHK; } break; case 'w': opts_f.f_writeu = 1; open_flags = O_RDWR; unique = strtoul(optarg, &endptr, 0); if ('\0' != *endptr) { if (errno) { perror("strtoul -w option"); } else { fprintf(stderr, "-w option strtoul error\n"); } goto L_close; } break; default: goto L_close; break; } } do { int f_1arg = opts_f.f_chk + opts_f.f_info + opts_f.f_format + opts_f.f_writeu; int f_2arg = opts_f.f_direct + opts_f.f_save; switch(argc - optind) { case 1: if (f_2arg || f_1arg == 0 || opts_f.f_force == 1) { fprintf(stderr, "invalid arguments.\n"); goto L_close; } file_in = argv[optind]; break; case 2: if (f_1arg) { fprintf(stderr, "invalid arguments.\n"); goto L_close; } if (f_2arg == 0) { opts_f.f_conv = 1; } file_in = argv[optind]; file_out = argv[optind+1]; break; default: fprintf(stderr, "invalid arguments.\n"); goto L_close; break; } } while(0); /* get boot architecture */ if (uname(&utsname) < 0) { perror("uname"); goto L_close; } if (strncmp(utsname.machine, "i386", 4) == 0) { arch_uname = DUMP_ARCH_I386; } else if (strncmp(utsname.machine, "i686", 4) == 0) { arch_uname = DUMP_ARCH_I386; } else if (strncmp(utsname.machine, "x86_64", 6) == 0) { arch_uname = DUMP_ARCH_X8664; } else if (strncmp(utsname.machine, "ia64", 4) == 0) { arch_uname = DUMP_ARCH_IA64; } else { fprintf(stderr, "invalid architecture(in uname).\n"); goto L_close; } if (arch_in) { arch = arch_in; } else { arch = arch_uname; } dcache.arch = arch; dcache.buf_sz = dcache.p_sz * dcache.p_num; if ((result = posix_memalign((void *)&(dcache.buf), 512, dcache.buf_sz)) != 0) { /* posix_memalign() is not set errno. */ fprintf(stderr, "posix_memalign(for cache of dump data) : %d", result); goto L_close; } memset(dcache.buf, 0, dcache.buf_sz); // open_flags |= O_DIRECT; fd_in = open(file_in, open_flags); if (fd_in < 0) { perror("open input file"); goto L_close; } if (file_out != NULL) { open_flags = O_WRONLY | O_CREAT | O_EXCL; fd_out = open(file_out, open_flags, 0444); if (fd_out < 0) { perror("open output file"); goto L_close; } } /* format dump device */ if (opts_f.f_format) { if ((result = format_ddev(fd_in, file_in, &dcache, &f_sum)) < 0) { goto L_close; } goto L_normal; } /* copy dump without checking header) */ if (opts_f.f_direct && f_direct_chk == COPY_DUMP_NOCHK) { if ((res_conv = copy_dump_no_conv(fd_in, fd_out, file_in, &dcache, f_direct_chk, &f_sum)) < 0) { goto L_close; } goto L_normal; } /* read dump headers */ if ((result = get_headers(fd_in, &dcache, verbose)) < 0) { goto L_close; } if (dcache.r_dv || dcache.r_dm || dcache.r_dt) { res_header = -1; } /* * for each options */ /* get header information */ if (opts_f.f_info) { printf("%d %d %x\n", dcache.dvp->dv_version, dcache.dvp->dv_arch, dcache.dvp->dv_unique); if (res_header < 0) { goto L_close; } goto L_normal; } /* update dump unique */ if (opts_f.f_writeu) { result = update_header(fd_in, &dcache, unique, verbose); if (result < 0) { goto L_close; } goto L_normal; } /* copy dump with checking header */ if (opts_f.f_direct) { if ((res_conv = copy_dump_no_conv(fd_in, fd_out, file_in, &dcache, f_direct_chk, &f_sum)) < 0) { goto L_close; } goto L_normal; } /* check dump status */ if (opts_f.f_chk) { u64 blk; if (dcache.r_dv || dcache.r_dm) { goto L_close; } result = check_dump_stat(fd_in, &dcache, &blk); printf("%d %d\n", result, blk); if (result == 0) { goto L_normal; } else { goto L_close; } } /* convert mkdump to lkcd */ if (opts_f.f_save && res_header) { if ((res_conv = copy_dump_no_conv(fd_in, fd_out, file_in, &dcache, COPY_DUMP_NOCHK, &f_sum)) < 0) { goto L_close; } } else if (opts_f.f_force == 0 && res_header) { goto L_close; } else { if (dcache.dvp->dv_arch == DUMP_ARCH_I386) { res_conv = mkd2lkcd_i386(fd_in, fd_out, &dcache, &blk_cnt); } else if (dcache.dvp->dv_arch == DUMP_ARCH_X8664) { res_conv = mkd2lkcd_x86_64(fd_in, fd_out, &dcache, &blk_cnt); } else { fprintf_verb(verbose, "invalid architecture(in main)."); goto L_close; } f_sum = blk_cnt * dcache.p_sz; if (res_conv < 0) { goto L_close; } } L_normal: flg_remove = 0; ret = EXIT_OK; L_close: if (f_sum && verbose == CHECK_HEADER_VERBOSE) { printf("%lld blocks + %lld bytes (4096bytes/block)\n", f_sum / dcache.p_sz, f_sum % dcache.p_sz); printf("%lld bytes\n", f_sum); } if (fd_out >= 0) { if (close(fd_out) == 0) { if (flg_remove && opts_f.f_force == 0) { if (unlink(file_out) < 0) { perror("unlink output file"); } } } else { perror("close input file"); } } if (fd_in >= 0) { if (close(fd_in) < 0) { perror("close input file"); } } free(buf); free(dcache.buf); free(dcache.dtp); exit(ret); } /* * fprintf(stderr, ...) with cheking verbose */ void fprintf_verb(int verbose, char *msg) { if (msg == NULL) { fprintf(stderr, "no message.\n"); } else if (verbose == CHECK_HEADER_VERBOSE) { fprintf(stderr, "%s\n", msg); } } /* * check dump header */ int check_header(struct dump_version *dvp, int arch, int verbose) { DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); if (memcmp(dvp->dv_magic, DUMP_MAGIC, DUMP_MAGIC_LEN)) { fprintf_verb(verbose, "invalid dump magic."); return -1; } if (dvp->dv_version != DUMP_VERSION) { fprintf_verb(verbose, "invalid dump version."); return -2; } if (dvp->dv_arch != arch) { fprintf_verb(verbose, "unmatched architecture."); if (dvp->dv_arch == DUMP_ARCH_I386 || dvp->dv_arch == DUMP_ARCH_X8664 || dvp->dv_arch == DUMP_ARCH_IA64) { return -3; } else { fprintf_verb(verbose, "invalid architecture."); return -4; } } if (dvp->dv_unique == 0 || dvp->dv_unique == 0xffffffff) { fprintf_verb(verbose, "invalid dump unique."); return -5; } return 0; } /* * check memory segment header */ int check_memseg(struct mem_seg *dmp, u64 *blk, int verbose) { int i; DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); *blk = 0; if (dmp->seg_num > MAX_MEM_SEG || memcmp(dmp, DUMP_MAGIC, DUMP_MAGIC_LEN) == 0) { fprintf_verb(verbose, "invalid memseg list."); return -1; } /* get dump pages */ for (i = 0; i < dmp->seg_num; i++) { *blk += dmp->seg_list[i].seg_size; } return 0; } /* * check dump tailer */ int check_tailer(struct dump_version *dvp0, struct dump_version *dvp1, int arch, int verbose) { DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); if (check_header(dvp1, arch, verbose) < 0) { fprintf_verb(verbose, "invalid tailer."); return -1; } if (dvp0->dv_unique != dvp1->dv_unique) { fprintf_verb(verbose, "invalid tailer(unmatched dump unique)."); return -1; } return 0; } /* * get headers */ static int get_headers(int fd_in, dump_cache_t *dcache, int verbose) { int result; /* read dump headers */ if ((result = posix_memalign((void *)&(dcache->dvp), 512, dcache->p_sz * 2)) != 0) { /* posix_memalign() is not set errno. */ fprintf(stderr, "posix_memalign(for cache of dump headers) : %d", result); return -1; } if ((result = read(fd_in, dcache->dvp, dcache->p_sz * 2)) != dcache->p_sz * 2) { if (result < 0) { perror("read headers(in main)"); } else { fprintf(stderr, "header read size error(in main) %d : %d", dcache->p_sz * 2, result); } return -1; } dcache->dmp = (struct mem_seg *)((char *)(dcache->dvp) + dcache->p_sz); /* get header information */ dcache->r_dv = check_header(dcache->dvp, dcache->dvp->dv_arch, verbose); dcache->r_dm = check_memseg(dcache->dmp, &(dcache->blk), verbose); /* read dump tailer */ if (dcache->r_dv == 0 && dcache->r_dm == 0) { if (lseek(fd_in, dcache->blk * dcache->p_sz, SEEK_CUR) < 0) { perror("lseek tailer(in main)"); return -1; } if ((result = posix_memalign((void *)&(dcache->dtp), 512, dcache->p_sz)) != 0) { /* posix_memalign() is not set errno. */ fprintf(stderr, "posix_memalign(for cache of dump tailer) : %d", result); return -1; } if ((result = read(fd_in, dcache->dtp, dcache->p_sz)) != dcache->p_sz) { if (result < 0) { perror("read tailer(in main)"); } else { fprintf(stderr, "tailer read size error(in main) %d : %d", dcache->p_sz, result); } return -1; } dcache->r_dt = check_tailer(dcache->dvp, dcache->dtp, dcache->dvp->dv_arch, verbose); if (lseek(fd_in, dcache->p_sz * 2, SEEK_SET) != dcache->p_sz * 2) { perror("lseek header(in main)"); return -1; } } return 0; } /* * update header */ static int update_header(int fd, dump_cache_t *dcache, u32 unique, int verbose) { ssize_t wsz; DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); if (lseek(fd, 0, SEEK_SET) != 0) { perror("lseek(in update_header)"); return -1; } dcache->dvp->dv_unique = unique; if ((wsz = write(fd, dcache->dvp, dcache->p_sz)) != dcache->p_sz) { if (wsz < 0) { perror("write(in update_header)"); } else { fprintf(stderr, "header write size error(in update_header) %d : %d\n", dcache->p_sz, wsz); } return -1; } return 0; } /* * dump copy */ static int copy_dump_no_conv(int fd_in, int fd_out, char *file_nm, dump_cache_t *dcache, int chk, u64 *sum) { ssize_t rsz, wsz; size_t rqsz; int result, i, per = -1; u64 max_blk = 0, f_sz = 0; DPRINT(("Enter %s(%d), chk=%d\n", __FUNCTION__,__LINE__,chk)); *sum = 0; if (chk == COPY_DUMP_CHK) { if (dcache->r_dv == 0 && dcache->r_dm == 0) { max_blk = dcache->blk + 3; f_sz = max_blk * dcache->p_sz; } } if (f_sz == 0) { if ((result = check_devf(fd_in, file_nm, &f_sz)) < 0) { return -1; } } if (lseek(fd_in, 0, SEEK_SET) != 0) { perror("lseek(in copy_dump_no_conv)"); return -1; } if (f_sz && dcache->buf_sz > f_sz) { rqsz = f_sz; } else { rqsz = dcache->buf_sz; } do { if ((rsz = read(fd_in, dcache->buf, rqsz)) < 0) { perror("read dump(in copy_dump_no_conv)"); return -1; } if (rsz) { if ((wsz = write(fd_out, dcache->buf, rsz)) != rsz) { if (wsz < 0) { perror("write(in copy_dump_no_conv)"); } else { fprintf(stderr, "write size error(in copy_dump_no_conv) %d : %d\n", rsz, wsz); } return -1; } } if (rsz != dcache->buf_sz) { *sum += rsz; } else { *sum += dcache->buf_sz; if (f_sz && *sum + dcache->buf_sz > f_sz) { rqsz = f_sz - *sum; } else { rqsz = dcache->buf_sz; } } if (f_sz) { DSP_INDICATOR(f_sz, *sum, per); } if (rsz != dcache->buf_sz) { if (per != -1) { fprintf(stderr, "\n"); } break; } } while (rsz > 0); return 0; } /* * check dump status */ static int check_dump_stat(int fd, dump_cache_t *dcache, u64 *blk) { ssize_t rsz; u64 max_blk; struct dump_version *wdvp = NULL; char *wp; int i, f_end, per = -1; DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); /* check header */ *blk = 0; if (dcache->r_dv || dcache->r_dm) { fprintf(stderr, "invalid header(in check_dump_stat).\n"); return -1; } /* check tailer */ max_blk = dcache->blk + 3; /* for dump header, tailer */ if (dcache->r_dt == 0) { *blk = max_blk; return 0; } /* check number of dump pages */ if (lseek(fd, dcache->p_sz * 2, SEEK_SET) != dcache->p_sz * 2) { perror("lseek dump data(in check_dump_stat)"); return -1; } for (*blk = 2, f_end = 0, per = -1; *blk < max_blk;) { int rcnt; if ((rsz = read(fd, dcache->buf, dcache->buf_sz)) < 0) { perror("read dump(in check_dump_stat)"); return -1; } else if (rsz == 0) { break; } rcnt = rsz / dcache->p_sz; wp = dcache->buf; for(i = 0; i < rcnt; i++) { wdvp = (struct dump_version *)wp; if (memcmp(wdvp, DUMP_MAGIC, DUMP_MAGIC_LEN) == 0 && dcache->dvp->dv_unique != wdvp->dv_unique) { f_end = 1; break; } wp += dcache->p_sz; (*blk)++; DSP_INDICATOR(max_blk, *blk, per); } if (rsz != dcache->buf_sz || f_end) { break; } } if (per != -1) { fprintf(stderr, "\n"); } return 1; } /* * format dump device */ static int format_ddev(int fd, char *file_nm, dump_cache_t *dcache, u64 *sum) { ssize_t wsz; u64 blk_cnt = 0, max_blk, f_sz = 0; struct dump_version dh_version; char *wp; int i, result, per = -1; DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); *sum = 0; strncpy(dh_version.dv_magic, DUMP_MAGIC, DUMP_MAGIC_LEN); dh_version.dv_version = DUMP_VERSION; dh_version.dv_arch = dcache->arch; if ((result = check_devf(fd, file_nm, &f_sz)) < 0) { return -1; } else if (result > 0) { fprintf(stderr, "not device file(in format_ddev).\n"); return -1; } memset(dcache->buf, 0, dcache->buf_sz); wp = dcache->buf; for(i = 0; i < dcache->p_num; i++) { memcpy(wp, &dh_version, sizeof(dh_version)); wp += dcache->p_sz; } blk_cnt = 0; do { wp = dcache->buf; for(i = 0; i < dcache->p_num; i++) { ((struct dump_version *)wp)->dv_unique = blk_cnt; wp += dcache->p_sz; blk_cnt++; } if ((wsz = write(fd, dcache->buf, dcache->buf_sz)) != dcache->buf_sz) { if (wsz < 0) { perror("write(in format_ddev)"); return -1; } *sum += wsz; } else { *sum += dcache->buf_sz; } if (f_sz) { DSP_INDICATOR(f_sz, *sum, per); } if (wsz != dcache->buf_sz) { break; } } while (wsz > 0); if (per != -1) { fprintf(stderr, "\n"); } return 0; } /* * check if device file */ static int check_devf(int fd, char *file_nm, u64 *size) { struct stat stat_buf; FILE *fp; DIR *dp; char *str; char *endptr = NULL; char command[257]; char buf[257]; int lng; DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); *size = 0; if (fstat(fd, &stat_buf) < 0) { perror("fstat(in format_ddev)"); return -1; } else if (stat_buf.st_rdev == 0) { *size = stat_buf.st_size; return 1; } if ((dp = opendir("/sys")) != NULL) { closedir(dp); if ((str = strrchr(file_nm, '/')) == NULL) { fprintf(stderr, "invalid file name.\n"); return 2; } str++; /* get sysfs file path */ lng = snprintf(command, sizeof(command), "find /sys/block -name %s", str); if (lng > sizeof(command) || lng < 0) { fprintf(stderr, "too long file name.\n"); return -1; } if ((fp = popen(command, "r")) == NULL) { perror("popen(get path"); return 2; } if (fgets(buf, sizeof(buf), fp) == NULL) { pclose(fp); return 2; } if (pclose(fp) < 0) { perror("pclose"); } if ((str = strchr(buf, '\n')) != NULL) { *str = '\0'; } /* get device file size */ lng = snprintf(command, sizeof(command), "cat %s/size", buf); if (lng > sizeof(command) || lng < 0) { fprintf(stderr, "too long file name.\n"); return -1; } if ((fp = popen(command, "r")) == NULL) { perror("popen(get file size"); return 2; } if (fgets(buf, sizeof(buf), fp) == NULL) { pclose(fp); return 2; } if ((str = strchr(buf, '\n')) != NULL) { *str = '\0'; } if (pclose(fp) < 0) { perror("pclose"); } *size = strtoll(buf, &endptr, 0); if ('\0' != *endptr) { fprintf(stderr, "file size error.\n"); *size = 0; return -1; } *size = *size * 512; } return 0; } --- NEW FILE: mkd_conv_lkcd_x86_64.c --- /* * mkd_conv/mkd_conv_lkcd_x86_64.c * * $Id: mkd_conv_lkcd_x86_64.c,v 1.1 2006/03/03 00:00:01 fkak Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * 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 (version 2 of the License). * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <errno.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <fcntl.h> #include "typedefs.h" #include "kernel_x86_64.h" #include "minik_dump.h" #include "minik_dump_x86_64.h" #include "lkcd_dump_x86_64.h" #include "mkd_conv.h" /* buffers */ static char lkcd_header_buf[64 * 1024]; static MKDC_LKCD_DP_T lkcd_page_header; static int convert_header(struct dump_header_x86_64 *dhp, struct mem_seg *msegp, MKDC_LKCD_DH_T *lkcd_dhp, MKDC_LKCD_DHA_X86_64_T *lkcd_dahp, u64 total_page); int mkd2lkcd_x86_64(int in_fd, int out_fd, dump_cache_t *dcache, u64 *blk_cnt) { char *page_buf; int all_ok = 0; int i, per = -1; struct mem_seg *msegp; u64 pfn, end_pfn, sum; DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); *blk_cnt = 0; msegp = dcache->dmp; page_buf = dcache->buf; /* * read and check header */ if (check_header(dcache->dvp, DUMP_ARCH_X8664, CHECK_HEADER_NOVERBOSE) < 0) { goto out; } /* * convert header and write lkcd_header */ if (dcache->r_dm) { fprintf(stderr, "invalid memseg.\n"); goto out; } if (dcache->blk == 0) { fprintf(stderr, "no page.\n"); goto out; } sum = dcache->blk; if (convert_header((struct dump_header_x86_64 *)(dcache->dvp), msegp, (MKDC_LKCD_DH_T *)lkcd_header_buf, (MKDC_LKCD_DHA_X86_64_T *)(lkcd_header_buf + sizeof(MKDC_LKCD_DH_T)), dcache->blk) < 0) { goto out; } if (write(out_fd, lkcd_header_buf, sizeof(lkcd_header_buf)) != sizeof(lkcd_header_buf)) { if (errno) { perror("write header"); } else { fprintf(stderr, "header write size error.\n"); } goto out; } /* * write pages */ for (i = 0, *blk_cnt = 0, per = -1; i < msegp->seg_num; i++) { pfn = msegp->seg_list[i].seg_start_pfn; end_pfn = pfn + msegp->seg_list[i].seg_size; for (; pfn < end_pfn; pfn++) { if (read(in_fd, page_buf, PAGE_SIZE_X86_64) != PAGE_SIZE_X86_64) { if (errno) { perror("read page"); } else { fprintf(stderr, "page read size error.\n"); } goto out; } lkcd_page_header.address = pfn << PAGE_SHIFT_X86_64; lkcd_page_header.size = PAGE_SIZE_X86_64; lkcd_page_header.flags = MKDC_LKCD_DP_RAW; if (write(out_fd, &lkcd_page_header, sizeof(lkcd_page_header)) != sizeof(lkcd_page_header)) { if (errno) { perror("write page header"); } else { fprintf(stderr, "page header write size error.\n"); } goto out; } if (write(out_fd, page_buf, PAGE_SIZE_X86_64) != PAGE_SIZE_X86_64) { if (errno) { perror("write page"); } else { fprintf(stderr, "page write size error.\n"); } goto out; } (*blk_cnt)++; DSP_INDICATOR(sum, *blk_cnt, per); } } if (per != -1) { fprintf(stderr, "\n"); } lkcd_page_header.address = MKDC_LKCD_DP_ADDRESS_END; lkcd_page_header.size = 0; lkcd_page_header.flags = MKDC_LKCD_DP_RAW; if (write(out_fd, &lkcd_page_header, sizeof(lkcd_page_header)) != sizeof(lkcd_page_header)) { if (errno) { perror("write page header"); } else { fprintf(stderr, "page header write size error.\n"); } goto out; } /* * check tailer */ if (read(in_fd, page_buf, PAGE_SIZE_X86_64) != PAGE_SIZE_X86_64) { if (errno) { perror("read tailer"); } else { fprintf(stderr, "tailer read size error.\n"); } goto out; } if (check_tailer(dcache->dvp, (struct dump_version *)page_buf, DUMP_ARCH_X8664, CHECK_HEADER_NOVERBOSE) < 0) { goto out; } /* OK all done */ all_ok = 1; out: if (all_ok) return 0; else return -1; } /* * architecture dependent stuff */ static int convert_header(struct dump_header_x86_64 *dhp, struct mem_seg *msegp, MKDC_LKCD_DH_T *lkcd_dhp, MKDC_LKCD_DHA_X86_64_T *lkcd_dahp, u64 total_page) { int i; int current_cpu; int num_cpus; u32 thread_info; /* * set lkcd dump header */ memset(lkcd_dhp, 0, sizeof(MKDC_LKCD_DH_T)); lkcd_dhp->magic_number = MKDC_LKCD_DH_MAGIC_NUMBER; lkcd_dhp->version = MKDC_LKCD_DH_VERSION_NUMBER; lkcd_dhp->header_size = sizeof(MKDC_LKCD_DH_T); lkcd_dhp->dump_level = 0xf; /* XXX: should define macro ??? f ?????????*/ lkcd_dhp->page_size = msegp->page_size; lkcd_dhp->memory_size = total_page * msegp->page_size; lkcd_dhp->memory_start = (u64)PAGE_OFFSET_X86_64; lkcd_dhp->memory_end = MKDC_LKCD_DH_MAGIC_NUMBER; lkcd_dhp->num_dump_pages = total_page; memcpy(lkcd_dhp->panic_string, dhp->dh_panic_string, DUMP_PANIC_LEN); lkcd_dhp->time.tv_sec = dhp->dh_time.tv_sec; lkcd_dhp->time.tv_usec = dhp->dh_time.tv_nsec / 1000; memcpy(lkcd_dhp->utsname_sysname, dhp->dh_utsname.sysname, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_nodename, dhp->dh_utsname.nodename, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_release, dhp->dh_utsname.release, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_version, dhp->dh_utsname.version, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_machine, dhp->dh_utsname.machine, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_domainname, dhp->dh_utsname.domainname, MKDC_LKCD_DH_UTS_LEN); current_cpu = dhp->dh_dump_cpu; if (current_cpu < 0 || current_cpu > MKDC_LKCD_HDA_MAX_NUM_CPUS_X86_64) { fprintf(stderr, "invalid dump_cpu.\n"); return -1; } lkcd_dhp->current_task = dhp->dh_tasks[current_cpu]; lkcd_dhp->dump_compress = MKDC_LKCD_DH_COMPRESS_NONE; lkcd_dhp->dump_flags = MKDC_LKCD_DH_FLAGS_DISKDUMP; /* lkcd_dhp->dump_device: N/A */ /* * set lkcd dump arch header (x86_64) */ memset(lkcd_dahp, 0, sizeof(MKDC_LKCD_DHA_X86_64_T)); lkcd_dahp->magic_number = MKDC_LKCD_HDA_MAGIC_NUMBER_X86_64; lkcd_dahp->version = MKDC_LKCD_HDA_VERSION_NUMBER_X86_64; lkcd_dahp->header_size = sizeof(MKDC_LKCD_DHA_X86_64_T); lkcd_dahp->regs = dhp->dh_regs[current_cpu]; num_cpus = 0; for( i = 0; i < DUMP_NR_CPUS; i++ ) { if (dhp->dh_tasks[i]) { num_cpus++; } } lkcd_dahp->smp_num_cpus = num_cpus; lkcd_dahp->dumping_cpu = current_cpu; memcpy(lkcd_dahp->smp_regs, dhp->dh_regs, sizeof(struct pt_regs_x86_64) * DUMP_NR_CPUS); memcpy(lkcd_dahp->smp_current_task, dhp->dh_tasks, sizeof(u32) * DUMP_NR_CPUS); for (i = 0; i < DUMP_NR_CPUS; i++) { if (dhp->dh_tasks[i]) { thread_info = dhp->dh_regs[i].rsp & (~8191); lkcd_dahp->stack[i] = thread_info; lkcd_dahp->stack_ptr[i] = thread_info; } } return 0; } --- NEW FILE: mkd_conv_lkcd_i386.c --- /* * mkd_conv/mkd_conv_lkcd_i386.c * * $Id: mkd_conv_lkcd_i386.c,v 1.1 2006/03/03 00:00:01 fkak Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * 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 (version 2 of the License). * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <errno.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <fcntl.h> #include "typedefs.h" #include "kernel_x86.h" #include "minik_dump.h" #include "minik_dump_i386.h" #include "lkcd_dump_x86.h" #include "mkd_conv.h" /* buffers */ static char lkcd_header_buf[64 * 1024]; static MKDC_LKCD_DP_T lkcd_page_header; static int convert_header(struct dump_header_i386 *dhp, struct mem_seg *msegp, MKDC_LKCD_DH_T *lkcd_dhp, MKDC_LKCD_DHA_X86_T *lkcd_dahp, u64 total_page); int mkd2lkcd_i386(int in_fd, int out_fd, dump_cache_t *dcache, u64 *blk_cnt) { char *page_buf; int all_ok = 0; int i, per = -1; struct mem_seg *msegp; u64 pfn, end_pfn, sum; DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); *blk_cnt = 0; msegp = dcache->dmp; page_buf = dcache->buf; /* * read and check header */ if (check_header(dcache->dvp, DUMP_ARCH_I386, CHECK_HEADER_NOVERBOSE) < 0) { goto out; } /* * convert header and write lkcd_header */ if (dcache->r_dm) { fprintf(stderr, "invalid memseg.\n"); goto out; } if (dcache->blk == 0) { fprintf(stderr, "no page.\n"); goto out; } sum = dcache->blk; if (convert_header((struct dump_header_i386 *)(dcache->dvp), msegp, (MKDC_LKCD_DH_T *)lkcd_header_buf, (MKDC_LKCD_DHA_X86_T *)(lkcd_header_buf + sizeof(MKDC_LKCD_DH_T)), dcache->blk) < 0) { goto out; } if (write(out_fd, lkcd_header_buf, sizeof(lkcd_header_buf)) != sizeof(lkcd_header_buf)) { if (errno) { perror("write header"); } else { fprintf(stderr, "header write size error.\n"); } goto out; } /* * write pages */ for (i = 0, *blk_cnt = 0, per = -1; i < msegp->seg_num; i++) { pfn = msegp->seg_list[i].seg_start_pfn; end_pfn = pfn + msegp->seg_list[i].seg_size; for (; pfn < end_pfn; pfn++) { if (read(in_fd, page_buf, PAGE_SIZE_X86) != PAGE_SIZE_X86) { if (errno) { perror("read page"); } else { fprintf(stderr, "page read size error.\n"); } goto out; } lkcd_page_header.address = pfn << PAGE_SHIFT_X86; lkcd_page_header.size = PAGE_SIZE_X86; lkcd_page_header.flags = MKDC_LKCD_DP_RAW; if (write(out_fd, &lkcd_page_header, sizeof(lkcd_page_header)) != sizeof(lkcd_page_header)) { if (errno) { perror("write page header"); } else { fprintf(stderr, "page header write size error.\n"); } goto out; } if (write(out_fd, page_buf, PAGE_SIZE_X86) != PAGE_SIZE_X86) { if (errno) { perror("write page"); } else { fprintf(stderr, "page write size error.\n"); } goto out; } (*blk_cnt)++; DSP_INDICATOR(sum, *blk_cnt, per); } } if (per != -1) { fprintf(stderr, "\n"); } lkcd_page_header.address = MKDC_LKCD_DP_ADDRESS_END; lkcd_page_header.size = 0; lkcd_page_header.flags = MKDC_LKCD_DP_RAW; if (write(out_fd, &lkcd_page_header, sizeof(lkcd_page_header)) != sizeof(lkcd_page_header)) { if (errno) { perror("write page header"); } else { fprintf(stderr, "page write size error.\n"); } goto out; } /* * check tailer */ if (read(in_fd, page_buf, PAGE_SIZE_X86) != PAGE_SIZE_X86) { if (errno) { perror("read tailer"); } else { fprintf(stderr, "tailer read size error.\n"); } goto out; } if (check_tailer(dcache->dvp, (struct dump_version *)page_buf, DUMP_ARCH_I386, CHECK_HEADER_NOVERBOSE) < 0) { goto out; } /* OK all done */ all_ok = 1; out: if (all_ok) return 0; else return -1; } /* * architecture dependent stuff */ static int convert_header(struct dump_header_i386 *dhp, struct mem_seg *msegp, MKDC_LKCD_DH_T *lkcd_dhp, MKDC_LKCD_DHA_X86_T *lkcd_dahp, u64 total_page) { int i; int current_cpu; int num_cpus; u32 thread_info; /* * set lkcd dump header */ memset(lkcd_dhp, 0, sizeof(MKDC_LKCD_DH_T)); lkcd_dhp->magic_number = MKDC_LKCD_DH_MAGIC_NUMBER; lkcd_dhp->version = MKDC_LKCD_DH_VERSION_NUMBER; lkcd_dhp->header_size = sizeof(MKDC_LKCD_DH_T); lkcd_dhp->dump_level = 0xf; /* XXX: should define macro */ lkcd_dhp->page_size = msegp->page_size; lkcd_dhp->memory_size = total_page; /* XXX */ lkcd_dhp->memory_start = (u64)PAGE_OFFSET_X86; lkcd_dhp->memory_end = MKDC_LKCD_DH_MAGIC_NUMBER; lkcd_dhp->num_dump_pages = total_page; memcpy(lkcd_dhp->panic_string, dhp->dh_panic_string, DUMP_PANIC_LEN); lkcd_dhp->time.tv_sec = dhp->dh_time.tv_sec; lkcd_dhp->time.tv_usec = dhp->dh_time.tv_nsec / 1000; memcpy(lkcd_dhp->utsname_sysname, dhp->dh_utsname.sysname, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_nodename, dhp->dh_utsname.nodename, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_release, dhp->dh_utsname.release, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_version, dhp->dh_utsname.version, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_machine, dhp->dh_utsname.machine, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_domainname, dhp->dh_utsname.domainname, MKDC_LKCD_DH_UTS_LEN); current_cpu = dhp->dh_dump_cpu; if (current_cpu < 0 || current_cpu > MKDC_LKCD_HDA_MAX_NUM_CPUS_I386) { fprintf(stderr, "invalid dump_cpu.\n"); return -1; } lkcd_dhp->current_task = dhp->dh_tasks[current_cpu]; lkcd_dhp->dump_compress = MKDC_LKCD_DH_COMPRESS_NONE; lkcd_dhp->dump_flags = MKDC_LKCD_DH_FLAGS_DISKDUMP; /* lkcd_dhp->dump_device: N/A */ /* * set lkcd dump arch header (i386) */ memset(lkcd_dahp, 0, sizeof(MKDC_LKCD_DHA_X86_T)); lkcd_dahp->magic_number = MKDC_LKCD_HDA_MAGIC_NUMBER_I386; lkcd_dahp->version = MKDC_LKCD_HDA_VERSION_NUMBER_I386; lkcd_dahp->header_size = sizeof(MKDC_LKCD_DHA_X86_T); /* lkcd_dahp->esp: N/A ? */ /* lkcd_dahp->eip: N/A ? */ /* lkcd_dahp->regs: N/A ? */ num_cpus = 0; for( i = 0; i < DUMP_NR_CPUS; i++ ) { if (dhp->dh_tasks[i]) { num_cpus++; } } lkcd_dahp->smp_num_cpus = num_cpus; lkcd_dahp->dumping_cpu = current_cpu; memcpy(lkcd_dahp->smp_regs, dhp->dh_regs, sizeof(struct pt_regs_x86) * DUMP_NR_CPUS); memcpy(lkcd_dahp->smp_current_task, dhp->dh_tasks, sizeof(u32) * DUMP_NR_CPUS); for (i = 0; i < DUMP_NR_CPUS; i++) { if (dhp->dh_tasks[i]) { thread_info = dhp->dh_regs[i].esp & (~8191); lkcd_dahp->stack[i] = thread_info; lkcd_dahp->stack_ptr[i] = thread_info; } } return 0; } |
From: kaku <fk...@us...> - 2006-03-02 23:58:46
|
Update of /cvsroot/mkdump/utils/mkd_conv In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14349 Modified Files: Makefile Log Message: Added mkd_conv. Changed a make rules. Index: Makefile =================================================================== RCS file: /cvsroot/mkdump/utils/mkd_conv/Makefile,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** Makefile 9 Dec 2005 13:34:19 -0000 1.8 --- Makefile 2 Mar 2006 23:58:40 -0000 1.9 *************** *** 20,44 **** CC = cc ! CFLAGS = -O -g -D _FILE_OFFSET_BITS=64 LDFLAGS = INCLUDES = -I ../include LIBS = ! TARGET = mkd2lkcd_x86_64 mkd2lkcd_i386 elf2lkcd_i386 ! OBJS = mkd2lkcd_x86_64.o mkd2lkcd_i386.o elf2lkcd_i386.o all: $(TARGET) ! mkd2lkcd_x86_64: mkd2lkcd_x86_64.o ! $(CC) $(LDFLAGS) -o $@ $@.o $(LIBS) ! ! mkd2lkcd_i386: mkd2lkcd_i386.o ! $(CC) $(LDFLAGS) -o $@ $@.o $(LIBS) ! elf2lkcd_i386: elf2lkcd_i386.o ! $(CC) $(LDFLAGS) -o $@ $@.o $(LIBS) .c.o: $(CC) $(CFLAGS) $(INCLUDES) -c $< clean: @rm -f $(TARGET) $(OBJS) *~ --- 20,44 ---- CC = cc ! CFLAGS = -O -g -D _FILE_OFFSET_BITS=64 -U_DEBUG_PRINT LDFLAGS = INCLUDES = -I ../include + HEADERS = elf.h elf32.h elf_x86.h kernel_defs.h kernel_x86.h \ + kernel_x86_64.h lkcd_dump.h lkcd_dump_x86.h lkcd_dump_x86_64.h mkd_conv.h LIBS = ! TARGET = mkd2lkcd_x86_64 mkd2lkcd_i386 elf2lkcd_i386 mkd_conv ! OBJS = mkd2lkcd_x86_64.o mkd2lkcd_i386.o elf2lkcd_i386.o mkd_conv.o mkd_conv_lkcd_i386.o mkd_conv_lkcd_x86_64.o all: $(TARGET) ! .o: ! $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) ! mkd_conv: mkd_conv.o mkd_conv_lkcd_i386.o mkd_conv_lkcd_x86_64.o .c.o: $(CC) $(CFLAGS) $(INCLUDES) -c $< + $(OBJS): $(HEADERS) + clean: @rm -f $(TARGET) $(OBJS) *~ |
From: Itsuro O. <od...@us...> - 2006-02-14 06:14:04
|
Update of /cvsroot/mkdump/minik/3.0/2.6/kernel In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23324/kernel Added Files: Makefile Makefile.base minik_dump.c mklds Log Message: first registration for mkdump v3.0 minik-module --- NEW FILE: minik_dump.c --- /* * kernel/minik_dump.c * * $Id: minik_dump.c,v 1.1 2006/02/14 06:13:53 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <linux/config.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/gfp.h> #include <linux/delay.h> #include <linux/reboot.h> #include <linux/blkdev.h> #include <linux/bootmem.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <asm/tlbflush.h> #include <asm/setup.h> MODULE_DESCRIPTION("Mini Kernel Dump"); MODULE_LICENSE("GPL"); #define MAX_MEM_SEG 62 /* struct mem_seg <= 4KB (1 page) */ #define MAX_RESERVE_SEG 32 struct mem_seg_list { u64 seg_start_pfn; u64 seg_size_pfn; }; struct mem_seg { u32 page_size; u32 seg_num; struct mem_seg_list seg_list[MAX_MEM_SEG]; }; static int dump_dev = 0; static unsigned long dump_pfn = 0; #define MAX_DUMP_DELAY 30 static int dump_delay = 0; #define MKDUMP_REBOOT 0 #define MKDUMP_HALT 1 #define MKDUMP_POWER_OFF 2 #define MKDUMP_NO_REBOOT 3 static int mkdump_reboot = MKDUMP_REBOOT; void do_dump(void); static int parse_mkdump_params(char *param, char *val) { if (!strcmp(param, "dump_dev")) { get_option(&val, &dump_dev); } else if (!strcmp(param, "dump_pfn")) { dump_pfn = simple_strtoul(val, NULL, 0); } else if (!strcmp(param, "mkdump_reboot")) { if (!strcmp(val, "halt")) { mkdump_reboot = MKDUMP_HALT; } else if (!strcmp(val, "poweroff")) { mkdump_reboot = MKDUMP_POWER_OFF; } else if (!strcmp(val, "no")) { mkdump_reboot = MKDUMP_NO_REBOOT; } } else if (!strcmp(param, "dump_delay")) { get_option(&val, &dump_delay); if (dump_delay > MAX_DUMP_DELAY) { dump_delay = MAX_DUMP_DELAY; } } return 0; } static int mkdump_init(void) { char tmp_cmdline[COMMAND_LINE_SIZE]; strlcpy(tmp_cmdline, saved_command_line, COMMAND_LINE_SIZE); parse_args("mkdump", tmp_cmdline, NULL, 0, parse_mkdump_params); if (dump_dev == 0) { printk("mkdump: no dump_dev defined. skip dump.\n"); return 0; } do_dump(); return 0; } static void mkdump_exit(void) { /* never called */ } module_init(mkdump_init); module_exit(mkdump_exit); /* * I/O stuff * * Mini dump kernel does not use filesystem layer but uses bio layer directly. * So the dump device must be a block device. */ static struct semaphore io_buff_sem; static int io_buff_io_err = 0; #define MINI_DUMP_BUFF_NUM 32 struct io_buff { struct io_buff *next; struct page *page; unsigned long pfn; }; static struct io_buff io_buff_array[MINI_DUMP_BUFF_NUM]; static struct io_buff *io_buff_head; static DEFINE_SPINLOCK(io_buff_lock); static struct block_device *bdev; static struct io_buff *get_io_buff(void) { struct io_buff *io_buff; unsigned long flags; down(&io_buff_sem); spin_lock_irqsave(&io_buff_lock, flags); io_buff = io_buff_head; io_buff_head = io_buff->next; spin_unlock_irqrestore(&io_buff_lock, flags); return io_buff; } static void put_io_buff(struct io_buff *io_buff) { unsigned long flags; spin_lock_irqsave(&io_buff_lock, flags); io_buff->next = io_buff_head; io_buff_head = io_buff; spin_unlock_irqrestore(&io_buff_lock, flags); up(&io_buff_sem); } static int mkdump_io_init(void) { int err; int i; bdev = bdget(dump_dev); if (bdev == NULL) { printk("mkdump: can't bdget\n"); return -1; } err = blkdev_get(bdev, 0, O_RDWR); if (err != 0) { printk("mkdump: blkdev_get error %d\n", err); return -1; } sema_init(&io_buff_sem, 0); for (i = 0; i < MINI_DUMP_BUFF_NUM; i++) { if ((io_buff_array[i].page = alloc_pages(GFP_KERNEL, 0)) == NULL) { printk("mkdump: alloc_pages error\n"); return -1; } put_io_buff(&io_buff_array[i]); } return 0; } static int mkdump_end_io(struct bio *bio, unsigned int bytes_done, int err) { struct io_buff *io_buff = bio->bi_private; if (err != 0) { printk("mkdump: I/O error %d. memory pfn = %lu\n", err, io_buff->pfn); io_buff_io_err = 1; } bio_put(bio); put_io_buff(io_buff); return 0; } #ifdef CONFIG_x86_64 static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t prot) { pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t *pte; pgd = pgd_offset_k(vaddr); if (pgd_none(*pgd)) { BUG(); return; } pud = pud_offset(pgd, vaddr); if (pud_none(*pud)) { BUG(); return; } pmd = pmd_offset(pud, vaddr); if (pmd_none(*pmd)) { BUG(); return; } pte = pte_offset_kernel(pmd, vaddr); set_pte(pte, pfn_pte(pfn, prot)); __flush_tlb_one(vaddr); } #endif static void *pfn_to_vaddr(unsigned long pfn) { void *vaddr = (void *)fix_to_virt(0); #ifdef CONFIG_x86_64 set_pte_pfn((unsigned long)vaddr, pfn, PAGE_READONLY); #else __set_fixmap(0, pfn << PAGE_SHIFT, PAGE_READONLY); #endif return vaddr; } static void mkdump_write(unsigned long pfn) { static unsigned long disk_page = 0; struct bio *bio; struct io_buff *io_buff; io_buff = get_io_buff(); memcpy(page_address(io_buff->page), pfn_to_vaddr(pfn), PAGE_SIZE); io_buff->pfn = pfn; bio = bio_alloc(GFP_NOIO, 1); /* no error ? */ bio->bi_bdev = bdev; bio->bi_vcnt = 1; bio->bi_idx = 0; bio->bi_end_io = mkdump_end_io; bio->bi_private = io_buff; bio->bi_sector = ((unsigned long long)disk_page << PAGE_SHIFT) >> 9; /* XXX */ bio->bi_size = PAGE_SIZE; bio->bi_io_vec[0].bv_page = io_buff->page; bio->bi_io_vec[0].bv_len = PAGE_SIZE; bio->bi_io_vec[0].bv_offset = 0; submit_bio(WRITE, bio); disk_page++; } static void mkdump_io_complete(void) { int i; for (i = 0; i < MINI_DUMP_BUFF_NUM; i++) { down(&io_buff_sem); } } static struct mem_seg mem_seg; static struct mem_seg reserve_seg; unsigned long convert_pfn(unsigned long pfn) { static int i = 0; static unsigned long vpfn = 0; for (; i < reserve_seg.seg_num; i++) { if (pfn < vpfn + reserve_seg.seg_list[i].seg_size_pfn) { return reserve_seg.seg_list[i].seg_start_pfn + pfn - vpfn; } vpfn += reserve_seg.seg_list[i].seg_size_pfn; } return pfn; } void do_dump(void) { int i; if (dump_pfn <= 0) { printk("mkdump: Invalid dump_pfn==0x%lx !\n", dump_pfn); goto reboot; } if (dump_delay > 0) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(dump_delay * HZ); } memcpy(&mem_seg, pfn_to_vaddr(dump_pfn + 1), sizeof(struct mem_seg)); if (mem_seg.seg_num == 0 || mem_seg.seg_num > MAX_MEM_SEG || mem_seg.page_size != PAGE_SIZE) { printk("mkdump: Invalid 'mem_seg' of dump_pfn!\n"); goto reboot; } memcpy(&reserve_seg, pfn_to_vaddr(dump_pfn + 2), sizeof(struct mem_seg)); if (reserve_seg.seg_num == 0 || reserve_seg.seg_num > MAX_RESERVE_SEG || reserve_seg.page_size != PAGE_SIZE) { printk("mkdump: Invalid 'reserve_seg' of dump_pfn!\n"); goto reboot; } if (mkdump_io_init() < 0) { goto reboot; } printk("Dump start. dump device = 0x%lx\n", (unsigned long)dump_dev); mkdump_write(dump_pfn); /* at first write dump header & memory segment list */ mkdump_write(dump_pfn + 1); /* 'mem_seg' memory map. */ /* dump real pages */ for (i = 0; i < mem_seg.seg_num; i++) { struct mem_seg_list *list = &mem_seg.seg_list[i]; unsigned long pfn; printk(" - Dumping pfn 0x%lx - 0x%lx (%ld pages) ", (unsigned long)(list->seg_start_pfn), (unsigned long)(list->seg_start_pfn + list->seg_size_pfn - 1), (unsigned long)(list->seg_size_pfn)); for (pfn = list->seg_start_pfn; pfn < list->seg_start_pfn + list->seg_size_pfn; pfn++) { if (io_buff_io_err) { goto reboot; } mkdump_write(convert_pfn(pfn)); if (pfn % 1024 == 0) printk("."); } printk("\n"); } mkdump_write(dump_pfn); /* at last write dump header once more */ mkdump_io_complete(); /* wait all I/Os completion */ printk("Dump done.\n"); reboot: switch (mkdump_reboot) { case MKDUMP_NO_REBOOT: return; case MKDUMP_REBOOT: printk("Preparing for the system reboot...\n"); mdelay(3000); system_state = SYSTEM_RESTART; device_shutdown(); printk("System reboot.\n"); mdelay(2000); /* Show the messages above for a while. */ machine_restart(NULL); break; case MKDUMP_HALT: printk("Preparing for the system halt...\n"); mdelay(3000); system_state = SYSTEM_HALT; device_shutdown(); printk("System halted.\n"); machine_halt(); break; case MKDUMP_POWER_OFF: printk("Preparing for the power down...\n"); mdelay(3000); system_state = SYSTEM_POWER_OFF; device_shutdown(); printk("Power down.\n"); mdelay(2000); /* Show the messages above for a while. */ machine_power_off(); break; } while (1) { cpu_relax(); } } #define IMPORT_SYMBOL(symbol) IMPORT_SYMBOL(parse_args); IMPORT_SYMBOL(__set_fixmap); IMPORT_SYMBOL(saved_command_line); IMPORT_SYMBOL(device_shutdown); --- NEW FILE: Makefile --- # # Makefile # # Portions Copyright 2004 NTT DATA CORPORATION. # Portions Copyright 2004 VA Linux Systems Japan K.K. # ARCH = i386 KMODSRC := mkdump.c KMODOBJ := $(KMODSRC:.c=.o) ifeq ($(ARCH),i386) KARCHOBJ := endif ifeq ($(ARCH),x86_64) KARCHOBJ := endif EXTRA_LDFLAGS := -T $(PWD)/sym.lds mkdump-objs:= minik_dump.o $(KARCHOBJ) KMOD_KO := $(KMODOBJ:.o=.ko) ifneq ($(KERNELRELEASE),) obj-m := $(KMODOBJ) else include Makefile.base endif --- NEW FILE: mklds --- #!/bin/bash SYSTEMMAP=$1 IMPORT_FILE=$2 SYMS=`grep '^IMPORT_SYMBOL' $IMPORT_FILE | sed -r 's/^IMPORT_SYMBOL\((\w+)\)\;/\1/'` for i in $SYMS do ADDR=`cat $SYSTEMMAP | awk '$3=="'$i'"{ print $1 }'` echo "$i = 0x$ADDR ;" done --- NEW FILE: Makefile.base --- # # Makefile.base # # Portions Copyright 2004 NTT DATA CORPORATION. # Portions Copyright 2004 VA Linux Systems Japan K.K. # CFLAGS= CC= gcc LD= ld KVER= 2.6.12small KDIR= /home/src/linux-2.6.12-small #KDIR= /home/src/linux-2.6.12-mkexec-test SBINDIR= /usr/sbin KMODDIR= /lib/modules/2.6.12small ARCHDIR= arch/$(ARCH)/kernel PWD= $(shell pwd) all: build build: sym.lds kmodules kmodules: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules sym.lds: ./mklds $(KDIR)/System.map minik_dump.c > sym.lds install: kmodules [ -d $(KMODDIR)/kernel/$(ARCHDIR) ] || \ mkdir -p $(KMODDIR)/kernel/$(ARCHDIR) for p in $(KMOD_KO); do \ install -c -m 644 $$p $(KMODDIR)/kernel/$(ARCHDIR)/$$p; \ done uninstall: for p in $(KMOD_KO); do \ rm -f $(KMODDIR)/kernel/$(ARCHDIR)/$$p; \ done clean : -rm -rf $(KMOD_KO) *.o .?*.cmd ?*.mod.c core .tmp_versions ../$(ARCHDIR)/*.o ../$(ARCHDIR)/.?*.cmd ../$(ARCHDIR)/?*.mod.c sym.lds |
From: Itsuro O. <od...@us...> - 2006-02-14 06:14:03
|
Update of /cvsroot/mkdump/minik/3.0/2.6 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23324 Added Files: Makefile Log Message: first registration for mkdump v3.0 minik-module --- NEW FILE: Makefile --- # # Makefile # # Portions Copyright 2004 NTT DATA CORPORATION. # Portions Copyright 2004 VA Linux Systems Japan K.K. # PWD= $(shell pwd) export EXTRA_CFLAGS= -I$(PWD)/include all: make -C ./kernel all clean: make -C ./kernel clean install: make -C ./kernel install uninstall: make -C ./kernel uninstall |
From: Itsuro O. <od...@us...> - 2006-02-14 06:11:52
|
Update of /cvsroot/mkdump/minik/3.0/2.6/kernel In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22835/3.0/2.6/kernel Log Message: Directory /cvsroot/mkdump/minik/3.0/2.6/kernel added to the repository |
From: Itsuro O. <od...@us...> - 2006-02-14 06:11:42
|
Update of /cvsroot/mkdump/minik/3.0/2.6 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22788/3.0/2.6 Log Message: Directory /cvsroot/mkdump/minik/3.0/2.6 added to the repository |
From: Itsuro O. <od...@us...> - 2006-02-14 06:11:30
|
Update of /cvsroot/mkdump/minik/3.0 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22768/3.0 Log Message: Directory /cvsroot/mkdump/minik/3.0 added to the repository |
From: Itsuro O. <od...@us...> - 2006-02-14 05:50:38
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/kernel In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17390/kernel Modified Files: Makefile.24 Makefile.26 minik_dump.c mkexec_main.c Log Message: the v3.0 initial Index: minik_dump.c =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/kernel/minik_dump.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** minik_dump.c 14 Feb 2006 05:30:27 -0000 1.1 --- minik_dump.c 14 Feb 2006 05:50:28 -0000 1.2 *************** *** 45,54 **** #include <asm/minik_dump.h> - /* - * start_dump() may crash and we get called again. - * It occurs at least from: lapic_mkexec_restore() - */ - #define LOOPING_MAX 5 - extern void (*do_dump_func)(char *, struct pt_regs *); --- 45,48 ---- *************** *** 56,61 **** static int minik_dump_cpu = NR_CPUS; - static int looping_count = 0; - void do_minik_dump(char *panic_str, struct pt_regs *regs) { --- 50,53 ---- *************** *** 72,84 **** } else { if (minik_dump_cpu == cpu) { ! looping_count++; ! printk("minik: Dump called by the dump routine (looped %d times, max is %d):\n", ! looping_count, LOOPING_MAX); dump_stack(); ! if (looping_count >= LOOPING_MAX) { ! printk("minik: Giving up.\n"); ! machine_restart(NULL); ! /* NOTREACHED */ ! } } else { printk("minik: Dump called by another cpu(%d)\n", cpu); --- 64,72 ---- } else { if (minik_dump_cpu == cpu) { ! printk("minik: Dump called by the dump routine\n"); dump_stack(); ! printk("minik: Giving up.\n"); ! machine_restart(NULL); ! /* NOTREACHED */ } else { printk("minik: Dump called by another cpu(%d)\n", cpu); *************** *** 104,111 **** init_dump_header(image); #ifdef MKEXEC_NO_PATCH ! /* only support RHEL currently */ ! netdump_func = do_minik_netdump; #else do_dump_func = do_minik_dump; #endif } --- 92,112 ---- init_dump_header(image); #ifdef MKEXEC_NO_PATCH ! netdump_func = do_minik_netdump; /* only support RHEL currently */ #else do_dump_func = do_minik_dump; #endif } + + void reserve_seg_init(struct kimage *image, struct mem_seg *mem_segp) + { + int i; + + mem_segp->page_size = PAGE_SIZE; + mem_segp->seg_num = image->num_minik_mem; + + for (i = 0; i < image->num_minik_mem; i++) { + mem_segp->seg_list[i].seg_start_pfn = image->reserve_mem[i].base_pa >> PAGE_SHIFT; + mem_segp->seg_list[i].seg_size_pfn = image->reserve_mem[i].size_bytes >> PAGE_SHIFT + ; + } + } Index: Makefile.26 =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/kernel/Makefile.26,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** Makefile.26 14 Feb 2006 05:30:27 -0000 1.1 --- Makefile.26 14 Feb 2006 05:50:28 -0000 1.2 *************** *** 29,33 **** endif ifeq ($(ARCH),x86_64) ! KARCHOBJ := ../arch/x86_64/kernel/machine_mkexec.o ../arch/x86_64/kernel/mkexec-vmlinux.o ../arch/x86_64/kernel/minik_dump.o ../arch/x86_64/kernel/start_new_kernel.o ../arch/x86_64/kernel/x86_64-setup-32.o endif --- 29,33 ---- endif ifeq ($(ARCH),x86_64) ! KARCHOBJ := ../arch/x86_64/kernel/machine_mkexec.o ../arch/i386/kernel/mkexec-vmlinux.o ../arch/x86_64/kernel/minik_dump.o ../arch/x86_64/kernel/start_new_kernel.o ../arch/x86_64/kernel/x86_64-setup-32.o endif Index: Makefile.24 =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/kernel/Makefile.24,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** Makefile.24 14 Feb 2006 05:30:27 -0000 1.1 --- Makefile.24 14 Feb 2006 05:50:28 -0000 1.2 *************** *** 46,50 **** KARCHOBJ := \ ../arch/x86_64/kernel/machine_mkexec.o \ ! ../arch/x86_64/kernel/mkexec-vmlinux.o \ ../arch/x86_64/kernel/minik_dump.o \ ../arch/x86_64/kernel/start_new_kernel.o \ --- 46,50 ---- KARCHOBJ := \ ../arch/x86_64/kernel/machine_mkexec.o \ ! ../arch/i386/kernel/mkexec-vmlinux.o \ ../arch/x86_64/kernel/minik_dump.o \ ../arch/x86_64/kernel/start_new_kernel.o \ Index: mkexec_main.c =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/kernel/mkexec_main.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** mkexec_main.c 14 Feb 2006 05:30:27 -0000 1.1 --- mkexec_main.c 14 Feb 2006 05:50:28 -0000 1.2 *************** *** 56,65 **** #include <asm/uaccess.h> #include <asm/setup.h> - #include <linux/mkexec.h> #include <asm/mkexec.h> #include <linux/minik_param.h> #include <asm/minik_dump.h> - #include <asm/io.h> --- 56,63 ---- *************** *** 70,73 **** --- 68,152 ---- typedef struct crashmem *(crashmem_get_t)(int); + struct copy_pages { + unsigned long src_start; + unsigned long dst_start; + unsigned long num_pages; + unsigned long is_swap; + }; + + static void make_copy_pages(struct kimage *kimage) + { + int i, j; + unsigned long src_addr, dst_addr, seg_addr; + unsigned long src_start, dst_start; + unsigned long mem_size, seg_size, size; + int is_swap; + struct copy_pages *cp; + + cp = (struct copy_pages *)(__va(kimage->swap_page_addr) + PAGE_SIZE); + + j = 0; + seg_addr = (unsigned long)kimage->segment[j].mem; + seg_size = ((kimage->segment[j].memsz + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; + for (i = 0; i < kimage->num_minik_mem; i++) { + src_addr = (unsigned long)i * MINIK_SEG_SIZE; + dst_addr = kimage->reserve_mem[i].base_pa; + mem_size = MINIK_SEG_SIZE; + + while (1) { + src_start = src_addr; + dst_start = dst_addr; + if (src_addr == seg_addr) { + size = mem_size < seg_size ? mem_size : seg_size; + seg_addr += size; + seg_size -= size; + is_swap = 1; + } else if (src_addr < seg_addr) { + size = seg_addr < src_addr + mem_size ? seg_addr - src_addr : mem_size; + is_swap = 0; + } else { + /* src_addr > seg_addr */ + /* not happen since mem is contiguous */ + } + cp->src_start = src_start; + cp->dst_start = dst_start; + cp->num_pages = size / PAGE_SIZE; + cp->is_swap = is_swap; + cp++; + if (seg_size == 0) { + j++; + if (j < kimage->nr_segments) { + seg_addr = (unsigned long)kimage->segment[j].mem; + seg_size = kimage->segment[j].memsz; + seg_size = ((seg_size + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; + } else { + seg_addr = (unsigned long)0xffffffff; + } + } + mem_size -= size; + if (mem_size == 0) { + break; + } else { + src_addr += size; + dst_addr += size; + } + } + } + cp->num_pages = 0; + + #if 1 + cp = (struct copy_pages *)(__va(kimage->swap_page_addr) + PAGE_SIZE); + while (1) { + if (cp->num_pages == 0) { + break; + } + printk("%x %x %x %x\n", cp->src_start, + cp->dst_start, cp->num_pages, cp->is_swap); + cp++; + } + #endif + return; + } + static int kimage_alloc_reserve(struct kimage *image) { *************** *** 98,103 **** image->num_minik_mem = 1; - image->new_kernel_paddr = image->reserve_mem[0].base_pa; /* ODA: common? */ - image->reboot_code_addr = image->new_kernel_paddr; /* ODA: common? */ return 0; --- 177,180 ---- *************** *** 110,117 **** int i; ! if ((mkexec_inf.mem & MINIK_SEG_MASK) != 0 || ! mkexec_inf.mem > MAX_MINIK_MEM_SEG * MINIK_SEG_SIZE) { return -EINVAL; ! }/* ODA: x86_64 ?? */ num_seg = mkexec_inf.mem >> MINIK_SEG_SHIFT; --- 187,193 ---- int i; ! if (mkexec_inf.mem == 0) { return -EINVAL; ! } num_seg = mkexec_inf.mem >> MINIK_SEG_SHIFT; *************** *** 127,138 **** image->reserve_mem[i].pages = pages; image->reserve_mem[i].order = order; } - image->num_minik_mem = num_seg; - image->new_kernel_paddr = image->reserve_mem[0].base_pa; /* ODA: common? */ - image->reboot_code_addr = image->new_kernel_paddr; /* ODA: common? */ return 0; } static int kimage_alloc(struct kimage *image) { --- 203,228 ---- image->reserve_mem[i].pages = pages; image->reserve_mem[i].order = order; + image->num_minik_mem++; /* for free */ } return 0; } + static int check_overlap(struct kimage *image) + { + int i; + unsigned long size = 0; + + for (i = 0; i < image->num_minik_mem; i++) { + size += image->reserve_mem[i].size_bytes; + } + for (i = 0; i < image->num_minik_mem; i++) { + if (image->reserve_mem[i].base_pa < size) { + return -1; + } + } + return 0; + } + static int kimage_alloc(struct kimage *image) { *************** *** 143,157 **** return result; } ! /* two pages: dump header + mem_seg */ ! image->dump_header_pages = alloc_pages(GFP_KERNEL, 1); if (!image->dump_header_pages) { return -ENOMEM; } image->nr_segments = 2; image->segment[0].mem = (void *)0x90000; /* setup */ image->segment[1].mem = (void *)0x100000; /* kernel 1MB */ ! // image->segment[2].mem = (void *)0x800000; /* initrd 8MB */ return 0; --- 233,260 ---- return result; } + image->new_kernel_paddr = image->reserve_mem[0].base_pa; ! /* 4 pages: dump header + mem_seg + reserve_mem + reboot_code */ ! image->dump_header_pages = alloc_pages(GFP_KERNEL, 2); if (!image->dump_header_pages) { return -ENOMEM; } + image->reboot_code_addr = (unsigned long)(page_to_pfn(image->dump_header_pages) << PAGE_SHIFT) + 3 * PAGE_SIZE; + + if (mkexec_inf.swap_image) { + if (check_overlap(image) < 0) { + printk("mkexec: memory overlap. give up.\n"); + return -ENOMEM; + } + if (!(image->swap_page = alloc_pages(GFP_KERNEL, 1))) { + return -ENOMEM; + } + image->swap_page_addr = (unsigned long)(page_to_pfn(image->swap_page) << PAGE_SHIFT); + } image->nr_segments = 2; image->segment[0].mem = (void *)0x90000; /* setup */ image->segment[1].mem = (void *)0x100000; /* kernel 1MB */ ! image->segment[2].mem = (void *)0x800000; /* initrd 8MB */ return 0; *************** *** 160,169 **** static void kimage_copy_reboot_code_pages(struct kimage *image) { ! char *ptr ; ! /* copy it out */ ! ptr = (char *)kmap(pfn_to_page(image->reboot_code_addr >> PAGE_SHIFT)); ! memcpy(ptr, start_new_kernel, start_new_kernel_size); ! kunmap(pfn_to_page(image->reboot_code_addr >> PAGE_SHIFT)); } --- 263,287 ---- static void kimage_copy_reboot_code_pages(struct kimage *image) { ! memcpy((char *)__va(image->reboot_code_addr), start_new_kernel, start_new_kernel_size); ! } ! static char *mem_offset(struct kimage *image, unsigned long offset, unsigned long *len) ! { ! int i; ! char *addr; ! ! for (i = 0; i < image->num_minik_mem; i++) { ! if (offset < image->reserve_mem[i].size_bytes) { ! addr = (char *)(__va(image->reserve_mem[i].base_pa) + offset); ! if (len) { ! *len = image->reserve_mem[i].size_bytes - offset; ! } ! return addr; ! } else { ! offset -= image->reserve_mem[i].size_bytes; ! } ! } ! ! return NULL; } *************** *** 176,225 **** return -EINVAL; } ! if (!memcmp((u8 *)image->segment[1].buf + MINIK_SIGNATURE_OFFSET, MINIK_SIGNATURE_HEAD, strlen(MINIK_SIGNATURE_HEAD))) { image->minik_type = MINIK_V2; } return 0; } ! static int kimage_load(struct kimage *image) { ! loff_t file_size; ! int read_size; struct file *file; ! int result = 0; ! mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); ! file = filp_open(mkexec_inf.path, O_RDONLY, 0); if (IS_ERR(file)) { ! printk("mkexec: can't open %s\n", mkexec_inf.path); ! return -1; } ! image->segment[1].buf = __va(image->new_kernel_paddr + image->segment[1].mem); ! file_size = file->f_dentry->d_inode->i_size; ! if (image->reserve_mem[0].size_bytes < file_size+4) { ! printk("mkexec: Trying to load too big kernel image" ! " (file=%lld bytes, /proc/mkexec/mem=%lu bytes)\n", ! (long long)file_size, image->reserve_mem[0].size_bytes); ! result = -1; ! goto out; } ! if ((read_size = kernel_read(file, 0, image->segment[1].buf, file_size+4)) < 0) { ! printk("mkexec: mini-kernel read NG(%d): %s\n", read_size, mkexec_inf.path); ! result = -1; ! goto out; ! } ! if (file_size != read_size){ ! printk("mkexec: read_size is not file_size. read_size=%d, file_size=%lld\n", ! read_size, (long long)file_size); ! result = -1; goto out; } - - image->segment[1].bufsz = image->segment[1].memsz = file_size; - result = kimage_check(image); out: set_fs(old_fs); --- 294,351 ---- return -EINVAL; } ! if (!memcmp((u8 *)mem_offset(image, (unsigned long)image->segment[1].mem, 0) + MINIK_SIGNATURE_OFFSET, MINIK_SIGNATURE_HEAD, strlen(MINIK_SIGNATURE_HEAD))) { image->minik_type = MINIK_V2; } + if (mkexec_inf.swap_image) { + image->minik_type = MINIK_V3; + } return 0; } ! static loff_t kimage_read_file(struct kimage *image, char *path, unsigned long start_offset) { ! loff_t file_size, size, file_off; struct file *file; ! loff_t result = -1; ! char *buf; ! unsigned long len; ! size_t cnt; mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); ! file = filp_open(path, O_RDONLY, 0); if (IS_ERR(file)) { ! printk("mkexec: can't open %s\n", path); ! return -1; /* XXX return errno */ } ! ! size = file_size = file->f_dentry->d_inode->i_size; ! file_off = 0; ! while (size > 0) { ! buf = mem_offset(image, start_offset, &len); ! if (buf == NULL) { ! break; ! } ! cnt = size > len ? len : size; ! if (kernel_read(file, file_off, buf, cnt) != cnt) { ! printk("mkexec: mini-kernel file read error\n"); ! result = -1; /* XXX errno? */ ! goto out; ! } ! size -= cnt; ! start_offset += cnt; ! file_off += cnt; } ! ! if (size > 0) { ! printk("mkexec: Trying to load too big kernel image (file=%lld bytes)\n", ! (long long)file_size); ! result = -1; /* XXX errno? */ goto out; } + result = file_size; + out: set_fs(old_fs); *************** *** 229,232 **** --- 355,393 ---- } + static int kimage_load(struct kimage *image) + { + loff_t file_size; + int result; + + if ((file_size = kimage_read_file(image, mkexec_inf.path, + (unsigned long)image->segment[1].mem)) < 0) { + return (int)file_size; + } + + image->segment[1].bufsz = image->segment[1].memsz = file_size; + result = kimage_check(image); + + return result; + } + + static int kimage_initrd_load(struct kimage *image) + { + loff_t file_size; + + if (!mkexec_inf.initrd[0]) { + return 0; + } + + if ((file_size = kimage_read_file(image, mkexec_inf.initrd, + (unsigned long)image->segment[2].mem)) < 0) { + return (int)file_size; + } + + image->segment[2].bufsz = image->segment[2].memsz = file_size; + image->nr_segments = 3; /* XXX */ + + return 0; + } + static int kimage_attr_prot(struct kimage *image, pgprot_t prot) { *************** *** 262,266 **** int i; ! if (!image){ return; } --- 423,427 ---- int i; ! if (!image) { return; } *************** *** 272,276 **** } if (image->dump_header_pages) { ! __free_pages(image->dump_header_pages, 1); } for (i = 0; i < image->num_control_page; i++) { --- 433,440 ---- } if (image->dump_header_pages) { ! __free_pages(image->dump_header_pages, 2); ! } ! if (image->swap_page) { ! __free_pages(image->swap_page, 1); } for (i = 0; i < image->num_control_page; i++) { *************** *** 352,355 **** --- 516,522 ---- goto out; } + if ((result = kimage_initrd_load(image)) != 0) { + goto out; + } if ((result = pimage_create(image)) != 0) { goto out; *************** *** 362,365 **** --- 529,536 ---- minik_dump_init(image); + if (mkexec_inf.swap_image) { + make_copy_pages(image); + } + if ((result = kimage_attr_prot(image, PAGE_KERNEL_RO)) != 0) { goto out; *************** *** 424,427 **** --- 595,599 ---- char mkexec_proc_path[] = "mkexec/path"; char mkexec_proc_parm[] = "mkexec/parameter"; + char mkexec_proc_initrd[] = "mkexec/initrd"; mkexec_mod_t mkexec_inf; *************** *** 495,501 **** --- 667,677 ---- (void)mkexec_unload(); mkexec_inf.stats = 0; + mkexec_inf.swap_image = 0; break; + case '9': + mkexec_inf.swap_image = 1; /* fall through */ case '1': /* mkexec load */ if (mkexec_load() < 0) { /* mini kernel loading */ + mkexec_inf.swap_image = 0; return -EPERM; break; *************** *** 601,604 **** --- 777,792 ---- } + static ssize_t + mkexec_read_initrd(struct file *file, char *ubuf, size_t cnt, loff_t *ppos) + { + return mkexec_proc_read(ubuf, mkexec_inf.initrd, cnt, ppos); + } + + static + ssize_t mkexec_write_initrd(struct file *file, const char *ubuf, size_t cnt, loff_t *ppos) + { + return mkexec_proc_write(ubuf, mkexec_inf.initrd, cnt, ppos, MKEXEC_MOD_MAXLEN); + } + static int mkexec_proc_open(struct inode *ip, struct file *fp) { *************** *** 651,654 **** --- 839,848 ---- .release = mkexec_proc_close }; + static struct file_operations mkexec_proc_initrd_op = { + .read = mkexec_read_initrd, + .write = mkexec_write_initrd, + .open = mkexec_proc_open, + .release = mkexec_proc_close + }; void mkexec_mod_exit(void) *************** *** 662,665 **** --- 856,860 ---- remove_proc_entry(mkexec_proc_ddev, 0); remove_proc_entry(mkexec_proc_base, 0); + remove_proc_entry(mkexec_proc_initrd, 0); } *************** *** 701,704 **** --- 896,904 ---- pe->proc_fops = &mkexec_proc_ddev_op; + if ((pe = create_proc_entry(mkexec_proc_initrd, 0, 0)) == NULL) { + goto out; + } + pe->proc_fops = &mkexec_proc_initrd_op; + return 0; |
From: Itsuro O. <od...@us...> - 2006-02-14 05:50:37
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/arch/i386/kernel In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17390/arch/i386/kernel Modified Files: machine_mkexec.c minik_dump.c mkexec-vmlinux.c start_new_kernel.S Log Message: the v3.0 initial Index: minik_dump.c =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/arch/i386/kernel/minik_dump.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** minik_dump.c 14 Feb 2006 05:30:26 -0000 1.1 --- minik_dump.c 14 Feb 2006 05:50:28 -0000 1.2 *************** *** 50,53 **** --- 50,54 ---- static struct dump_header *dhp; extern void mkexec_exec(void); + extern void reserve_seg_init(struct kimage *image, struct mem_seg *mem_segp); static void mem_seg_init(struct mem_seg *mem_segp) *************** *** 130,133 **** --- 131,136 ---- } *addrp = 0; + } else if (image->minik_type == MINIK_V3) { + reserve_seg_init(image, (void *)((u8 *)dhp + PAGE_SIZE * 2)); } } Index: start_new_kernel.S =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/arch/i386/kernel/start_new_kernel.S,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** start_new_kernel.S 14 Feb 2006 05:30:26 -0000 1.1 --- start_new_kernel.S 14 Feb 2006 05:50:28 -0000 1.2 *************** *** 31,34 **** --- 31,35 ---- movl 12(%esp), %edx /* start address */ movl 16(%esp), %ecx /* cpu_has_pae */ + movl 20(%esp), %eax /* swap page */ /* zero out flags, and disable interrupts */ *************** *** 40,43 **** --- 41,46 ---- /* store the parameters back on the stack */ pushl %edx /* store the start address */ + pushl %ebx + movl %eax, %ebx /* Set cr0 to a known state: *************** *** 70,77 **** --- 73,158 ---- movl %eax, %cr3 + cmpl $0, %ebx + je final + /* + * ### swap ### + */ + pushl %ebp + movl %ebx, %ebp + addl $4096, %ebp /* addr of copy_pages list */ + 1: + cmpl $0, 8(%ebp) /* if num_pages == 0 */ + je 2f + cmpl $0, 12(%ebp) /* if is_swap == 0 */ + je 4f + /* swap copy */ + movl 8(%ebp), %eax + 5: + cmpl $0, %eax + je 6f + pushl %eax + subl $1, %eax + shl $12, %eax + /* src -> work */ + movl (%ebp), %esi + addl %eax, %esi + movl %ebx, %edi + // addl %eax, %edi + movl $0x400, %ecx + cld + rep + movsl + /* dst -> src */ + movl 4(%ebp), %esi + addl %eax, %esi + movl (%ebp), %edi + addl %eax, %edi + movl $0x400, %ecx + cld + rep + movsl + /* work -> dst */ + movl %ebx, %esi + // addl %eax, %esi + movl 4(%ebp), %edi + addl %eax, %edi + movl $0x400, %ecx + cld + rep + movsl + popl %eax + subl $1, %eax + jmp 5b + 4: /* simple copy */ + movl (%ebp), %esi + movl 4(%ebp), %edi + movl 8(%ebp), %ecx + shl $10, %ecx /* pages -> words */ + cld + rep + movsl + 6: + addl $16, %ebp + jmp 1b + 2: /* end */ + popl %ebp + + #if 0 + /* copy first 4pages */ + movl %ebp, %esi + movl $0x0, %edi + movl $0x1000, %ecx + cld + rep + movsl + #endif + + final: + /* set all of the registers to known values */ /* leave %esp alone */ xorl %eax, %eax + popl %ebx /* xorl %ebx, %ebx *//* new address */ xorl %ecx, %ecx Index: machine_mkexec.c =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/arch/i386/kernel/machine_mkexec.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** machine_mkexec.c 14 Feb 2006 05:30:26 -0000 1.1 --- machine_mkexec.c 14 Feb 2006 05:50:28 -0000 1.2 *************** *** 120,124 **** typedef asmlinkage void (*start_new_kernel_t)( unsigned long indirection_page, unsigned long reboot_code_buffer, ! unsigned long start_address, unsigned int has_pae); const extern unsigned char start_new_kernel[]; --- 120,124 ---- typedef asmlinkage void (*start_new_kernel_t)( unsigned long indirection_page, unsigned long reboot_code_buffer, ! unsigned long start_address, unsigned int has_pae, unsigned long swap_page_addr); const extern unsigned char start_new_kernel[]; *************** *** 147,150 **** --- 147,152 ---- { start_new_kernel_t rnk; + unsigned long new_addr; + unsigned long start_addr; /* Interrupts aren't acceptable while we reboot */ *************** *** 176,181 **** /* now call it */ rnk = (start_new_kernel_t)image->reboot_code_addr; ! ! (*rnk)(image->new_kernel_paddr, image->reboot_code_addr, ! image->start+image->new_kernel_paddr, cpu_has_pae); } --- 178,188 ---- /* now call it */ rnk = (start_new_kernel_t)image->reboot_code_addr; ! if (image->minik_type == MINIK_V3) { ! new_addr = 0; ! start_addr = image->start; ! } else { ! new_addr = image->new_kernel_paddr; ! start_addr = image->start + image->new_kernel_paddr; ! } ! (*rnk)(new_addr, image->reboot_code_addr, start_addr, cpu_has_pae, image->swap_page_addr); } Index: mkexec-vmlinux.c =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/arch/i386/kernel/mkexec-vmlinux.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** mkexec-vmlinux.c 14 Feb 2006 05:30:26 -0000 1.1 --- mkexec-vmlinux.c 14 Feb 2006 05:50:28 -0000 1.2 *************** *** 161,165 **** int size; ! if (image->minik_type == MINIK_V1) { size = 0; for (i = 0; i < image->num_minik_mem; i++) { --- 161,165 ---- int size; ! if (image->minik_type == MINIK_V1 || image->minik_type == MINIK_V3) { size = 0; for (i = 0; i < image->num_minik_mem; i++) { *************** *** 167,170 **** --- 167,173 ---- } size = size / (1024 * 1024); + #ifdef CONFIG_X86_64 + size -= 1; + #endif buffer_append(buffer, " mem=%dM", size); return; *************** *** 186,206 **** } - static void string_arg_strip(char *string, const char *arg) - { - char *s, *s2; - - s = string; - while ((s = strstr(s, arg))) { - if (s > string && s[-1] != ' ') - continue; - s2 = s + strlen(arg); - while (*s2 && *s2 != ' ') - s2++; - while (*s2 == ' ') - s2++; - memmove(s, s2, strlen(s2) + 1); - } - } - int pimage_create(struct kimage *image) { --- 189,192 ---- *************** *** 223,237 **** * Prepare the minik command line arguments. */ ! /* Copy the current kernel's commandline. */ ! strncpy(image_command_line, saved_command_line, sizeof(image_command_line)); ! image_command_line[sizeof(image_command_line) - 1] = 0; ! /* Do not: append " crashkernel=no" ! * as the commandline may get too big to fit in. ! * Drop the original parameter instead. ! */ ! string_arg_strip(image_command_line, "crashdma="); ! string_arg_strip(image_command_line, "crashmain="); ! image_command_line_buffer.tail = image_command_line + strlen(image_command_line); ! if (image->minik_type == MINIK_V1) { buffer_append(&image_command_line_buffer, " dump_dev=%s maxcpus=1 noapic irqpoll", mkexec_inf.ddev); --- 209,219 ---- * Prepare the minik command line arguments. */ ! image_command_line[0] = 0; ! image_command_line_buffer.tail = image_command_line; ! if (image->minik_type == MINIK_V3) { ! buffer_append(&image_command_line_buffer, ! " dump_dev=%s dump_pfn=0x%lx maxcpus=1 noapic irqpoll", mkexec_inf.ddev, ! page_to_pfn(image->dump_header_pages)); ! } else if (image->minik_type == MINIK_V1) { buffer_append(&image_command_line_buffer, " dump_dev=%s maxcpus=1 noapic irqpoll", mkexec_inf.ddev); *************** *** 252,257 **** * These values are just random choice in the 640KB range. */ ! " memmap=64K@192K" ! , mkexec_inf.ddev, /* " dump_dev=%s" */ page_to_pfn(image->dump_header_pages)); /* " dump_pfn=0x%lx" */ --- 234,238 ---- * These values are just random choice in the 640KB range. */ ! " memmap=64K@192K" , mkexec_inf.ddev, /* " dump_dev=%s" */ page_to_pfn(image->dump_header_pages)); /* " dump_pfn=0x%lx" */ *************** *** 275,281 **** kern32_size = (setup_sects +1) *512; - // /* Can not get kernel version.(setup sector has version information.) */ - // kernel_version = ((unsigned char *)&header) + 512 + header.kver_addr; - /* The x86 code segment */ command_line_off = kern32_size; --- 256,259 ---- *************** *** 289,296 **** image->segment[0].memsz = image->segment[0].bufsz = size; ! ! image->segment[0].buf = (char *)((unsigned long)\ ! kmap(pfn_to_page(image->new_kernel_paddr >> PAGE_SHIFT)) ! + image->segment[0].mem); real_mode = image->segment[0].buf; cmdline = (char *)image->segment[0].buf + command_line_off; --- 267,271 ---- image->segment[0].memsz = image->segment[0].bufsz = size; ! image->segment[0].buf = __va(image->new_kernel_paddr + image->segment[0].mem); real_mode = image->segment[0].buf; cmdline = (char *)image->segment[0].buf + command_line_off; *************** *** 298,302 **** entry = (unsigned long)image->segment[0].mem + setup32_off; memset(image->segment[0].buf, 0, image->segment[0].bufsz); - kunmap(pfn_to_page(image->new_kernel_paddr>> PAGE_SHIFT)); /* --- 273,276 ---- *************** *** 306,314 **** real_mode->cl_magic = CL_MAGIC_VALUE; real_mode->cl_offset = command_line_off; - // if (header.protocol_version >= 0x0202) { - // real_mode->cmd_line_ptr = 0x90000 + command_line_off; - // } /* Provide absolute physical address of the commandline, it is not relocated. */ ! real_mode->cmd_line_ptr = __pa(cmdline); real_mode->heap_end_ptr = image->segment[0].bufsz + 1024; --- 280,289 ---- real_mode->cl_magic = CL_MAGIC_VALUE; real_mode->cl_offset = command_line_off; /* Provide absolute physical address of the commandline, it is not relocated. */ ! if (image->minik_type == MINIK_V3) { ! real_mode->cmd_line_ptr = 0x90000 + command_line_off; ! } else { ! real_mode->cmd_line_ptr = __pa(cmdline); ! } real_mode->heap_end_ptr = image->segment[0].bufsz + 1024; *************** *** 316,321 **** real_mode->loader_type = LOADER_TYPE_UNKNOWN; /* The ramdisk */ ! real_mode->initrd_start = 0; ! real_mode->initrd_size = 0; /* --- 291,301 ---- real_mode->loader_type = LOADER_TYPE_UNKNOWN; /* The ramdisk */ ! if (image->minik_type == MINIK_V3) { ! real_mode->initrd_start = image->segment[2].mem; ! real_mode->initrd_size = image->segment[2].memsz; ! } else { ! real_mode->initrd_start = 0; ! real_mode->initrd_size = 0; ! } /* |
From: Itsuro O. <od...@us...> - 2006-02-14 05:50:37
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/include/linux In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17390/include/linux Modified Files: mkexec.h Log Message: the v3.0 initial Index: mkexec.h =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/include/linux/mkexec.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** mkexec.h 14 Feb 2006 05:30:26 -0000 1.1 --- mkexec.h 14 Feb 2006 05:50:28 -0000 1.2 *************** *** 48,53 **** }; ! #define MINIK_V1 0 ! #define MINIK_V2 1 #define MKEXEC_CONTROL_PAGES_MAX 32 --- 48,54 ---- }; ! #define MINIK_V1 0 /* ture_phys version */ ! #define MINIK_V2 1 /* reltab version */ ! #define MINIK_V3 2 /* swap version */ #define MKEXEC_CONTROL_PAGES_MAX 32 *************** *** 56,59 **** --- 57,61 ---- unsigned long start; unsigned long reboot_code_addr; + struct page *reboot_code_pages; unsigned long nr_segments; /* ODA: remove --> enum */ struct mkexec_segment segment[MKEXEC_SEGMENT_MAX]; *************** *** 66,69 **** --- 68,73 ---- struct page *control_page[MKEXEC_CONTROL_PAGES_MAX]; struct page *dump_header_pages; + unsigned long swap_page_addr; + struct page *swap_page; }; *************** *** 88,94 **** char ddev[MKEXEC_MOD_MAXDEVLEN]; char memstr[MKEXEC_MOD_MAXDEVLEN]; int mem; atomic_t sem; ! int writ_cnt; } mkexec_mod_t; --- 92,99 ---- char ddev[MKEXEC_MOD_MAXDEVLEN]; char memstr[MKEXEC_MOD_MAXDEVLEN]; + char initrd[MKEXEC_MOD_MAXLEN]; int mem; atomic_t sem; ! int swap_image; } mkexec_mod_t; |
From: Itsuro O. <od...@us...> - 2006-02-14 05:50:37
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/arch/x86_64/kernel In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17390/arch/x86_64/kernel Modified Files: machine_mkexec.c minik_dump.c start_new_kernel.S Log Message: the v3.0 initial Index: minik_dump.c =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/arch/x86_64/kernel/minik_dump.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** minik_dump.c 14 Feb 2006 05:30:26 -0000 1.1 --- minik_dump.c 14 Feb 2006 05:50:28 -0000 1.2 *************** *** 49,52 **** --- 49,53 ---- static struct dump_header *dhp; extern void mkexec_exec(void); + extern void reserve_seg_init(struct kimage *image, struct mem_seg *mem_segp); static void mem_seg_init(struct mem_seg *mem_segp) *************** *** 129,133 **** } *addrp = 0; ! } } --- 130,136 ---- } *addrp = 0; ! } else if (image->minik_type == MINIK_V3) { ! reserve_seg_init(image, (void *)((u8 *)dhp + PAGE_SIZE * 2)); ! } } Index: start_new_kernel.S =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/arch/x86_64/kernel/start_new_kernel.S,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** start_new_kernel.S 14 Feb 2006 05:30:26 -0000 1.1 --- start_new_kernel.S 14 Feb 2006 05:50:28 -0000 1.2 *************** *** 32,36 **** * %rdx start address * %rcx page_table ! * %r8 arg5 * %r9 arg6 */ --- 32,36 ---- * %rdx start address * %rcx page_table ! * %r8 swap page * %r9 arg6 */ *************** *** 44,47 **** --- 44,48 ---- /* store the parameters back on the stack */ pushq %rdx /* store the start address */ + pushq %rdi /* Set cr0 to a known state: *************** *** 83,86 **** --- 84,152 ---- movq %rcx, %cr3 + /* add */ + cmpq $0, %r8 + je final + /* + * ### swap ### + */ + movq %r8, %r9 + addq $4096, %r9 /* addr of copy_pages list */ + 1: + cmpq $0, 16(%r9) /* if num_pages == 0 */ + je 2f + cmpq $0, 24(%r9) /* if is_swap == 0 */ + je 4f + /* swap copy */ + movq 16(%r9), %r10 + 5: + cmpq $0, %r10 + je 6f + pushq %r10 + subq $1, %r10 + shl $12, %r10 + /* src -> work */ + movq (%r9), %rsi + addq %r10, %rsi + movq %r8, %rdi + movq $0x200, %rcx + cld + rep + movsq + /* dst -> src */ + movq 8(%r9), %rsi + addq %r10, %rsi + movq (%r9), %rdi + addq %r10, %rdi + movq $0x200, %rcx + cld + rep + movsq + /* work -> dst */ + movq %r8, %rsi + movq 8(%r9), %rdi + addq %r10, %rdi + movq $0x200, %rcx + cld + rep + movsq + popq %r10 + subq $1, %r10 + jmp 5b + 4: /* simple copy */ + movq (%r9), %rsi + movq 8(%r9), %rdi + movq 16(%r9), %rcx + shl $9, %rcx /* pages -> words */ + cld + rep + movsq + 6: + addq $32, %r9 + jmp 1b + 2: /* end */ + + final: + /* add end */ + /* set all of the registers to known values */ /* leave %rsp alone */ *************** *** 91,94 **** --- 157,161 ---- xorq %rdx, %rdx xorq %rsi, %rsi + popq %rdi // xorq %rdi, %rdi xorq %rbp, %rbp Index: machine_mkexec.c =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/arch/x86_64/kernel/machine_mkexec.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** machine_mkexec.c 14 Feb 2006 05:30:26 -0000 1.1 --- machine_mkexec.c 14 Feb 2006 05:50:28 -0000 1.2 *************** *** 268,272 **** typedef asmlinkage void (*start_new_kernel_t)( unsigned long indirection_page, unsigned long reboot_code_buffer, ! unsigned long start_address, unsigned int has_pae); const extern unsigned char start_new_kernel[]; --- 268,272 ---- typedef asmlinkage void (*start_new_kernel_t)( unsigned long indirection_page, unsigned long reboot_code_buffer, ! unsigned long start_address, unsigned long start_pgtable, unsigned long swap_page); const extern unsigned char start_new_kernel[]; *************** *** 280,286 **** void machine_mkexec(struct kimage *image) { - unsigned long control_code_buffer; unsigned long start_pgtable; start_new_kernel_t rnk; /* Interrupts aren't acceptable while we reboot */ --- 280,287 ---- void machine_mkexec(struct kimage *image) { unsigned long start_pgtable; start_new_kernel_t rnk; + unsigned long new_addr; + unsigned long start_addr; /* Interrupts aren't acceptable while we reboot */ *************** *** 289,293 **** /* Calculate the offsets */ start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT; - control_code_buffer = image->reboot_code_addr; /* Set the low half of the page table to my identity mapped --- 290,293 ---- *************** *** 327,333 **** /* now call it */ rnk = (start_new_kernel_t)image->reboot_code_addr; ! ! (*rnk)(image->new_kernel_paddr, image->reboot_code_addr, ! image->start+image->new_kernel_paddr, start_pgtable); ! } --- 327,338 ---- /* now call it */ rnk = (start_new_kernel_t)image->reboot_code_addr; ! if (image->minik_type == MINIK_V3) { ! new_addr = 0; ! start_addr = image->start; ! } else { ! new_addr = image->new_kernel_paddr; ! start_addr = image->start + image->new_kernel_paddr; ! } ! (*rnk)(new_addr, image->reboot_code_addr, ! start_addr, start_pgtable, image->swap_page_addr); } |
From: Itsuro O. <od...@us...> - 2006-02-14 05:30:36
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/arch/i386/kernel In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12378/3.0/2.6/arch/i386/kernel Added Files: machine_mkexec.c minik_dump.c mkexec-vmlinux.c mkexec-x86.c start_new_kernel.S x86-setup-32.S Log Message: register for 3.0: based on 2.1 mkexec-2_0-linux-2_6-2_r --- NEW FILE: mkexec-vmlinux.c --- /* * arch/i386/kernel/mkexec-vmlinux.c * * mkexec: Linux boots Linux(Mini kernel) * * $Id: mkexec-vmlinux.c,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. */ /* * Some codes were derived from kexec : * * kexec: Linux boots Linux * * Copyright (C) 2003,2004 Eric Biederman (ebi...@xm...) * * 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 (version 2 of the License). * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/config.h> #include <linux/stddef.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/fcntl.h> #include <linux/stat.h> #include <linux/errno.h> #include <linux/unistd.h> #include <linux/proc_fs.h> #include <linux/ide.h> #include <linux/vmalloc.h> #include <linux/file.h> #include <asm/e820.h> #include <linux/mkexec.h> #include <asm/x86-linux.h> #include <asm/mkexec.h> #include <asm/mkexec-x86.h> extern char saved_command_line[]; int setup_linux_parameters(struct x86_linux_param_header *real_mode) { int i; /* Default screen size */ real_mode->orig_x = 0; real_mode->orig_y = 0; real_mode->orig_video_page = 0; real_mode->orig_video_mode = 0; real_mode->orig_video_cols = 80; real_mode->orig_video_lines = 25; real_mode->orig_video_ega_bx = 0; real_mode->orig_video_isVGA = 1; real_mode->orig_video_points = 16; /* Fill in the memsize later */ real_mode->ext_mem_k = 0; real_mode->alt_mem_k = 0; real_mode->e820_map_nr = 0; /* Default APM info */ memset(&real_mode->apm_bios_info, 0, sizeof(real_mode->apm_bios_info)); /* Default drive info */ memset(&real_mode->drive_info, 0, sizeof(real_mode->drive_info)); /* Default sysdesc table */ real_mode->sys_desc_table.length = 0; /* default yes: this can be overridden on the command line */ real_mode->mount_root_rdonly = 0xFFFF; /* default /dev/hda * this can be overrident on the command line if necessary. */ real_mode->root_dev = (0x3 <<8)| 0; /* another safe default */ real_mode->aux_device_info = 0; /* Fill in the memory info */ real_mode->e820_map_nr = e820.nr_map; memcpy(real_mode->e820_map, e820.map, sizeof(struct e820entry) * e820.nr_map); for(i = 0; i < e820.nr_map; i++) { if (real_mode->e820_map[i].type != RANGE_RAM) continue; if ((real_mode->e820_map[i].addr <= 0x100000) && real_mode->e820_map[i].addr + real_mode->e820_map[i].size > 0x100000) { unsigned long long mem_k = ((real_mode->e820_map[i].addr + real_mode->e820_map[i].size) >> 10) - 0x100000; real_mode->ext_mem_k = mem_k; real_mode->alt_mem_k = mem_k; if (mem_k > 0xfc00) { real_mode->ext_mem_k = 0xfc00; /* 64M */ } if (mem_k > 0xffffffff) { real_mode->alt_mem_k = 0xffffffff; } } } real_mode->setup_sects = 4; memcpy(real_mode->header_magic, "HdrS",4); real_mode->protocol_version = 0x0202; // real_mode->initrd_addr_max = 0x37ffffff; return 0; } struct buffer { char *tail; char *end; }; static void buffer_append(struct buffer *buffer, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); static void buffer_append(struct buffer *buffer, const char *fmt, ...) { va_list ap; ssize_t remains; remains = buffer->end - buffer->tail; if (remains <= 1) return; va_start(ap, fmt); buffer->tail += vsnprintf(buffer->tail, remains, fmt, ap); va_end(ap); } static void buffer_append_memparse(struct buffer *buffer, unsigned long long val) { const char *s = ""; /****/ if (!(val & ((1 << 30) - 1))) { val >>= 30; s = "G"; } else if (!(val & ((1 << 20) - 1))) { val >>= 20; s = "M"; } else if (!(val & ((1 << 10) - 1))) { val >>= 10; s = "K"; } /* Decimal is ugly but it is shorter, we need space! */ buffer_append(buffer, "%llu%s", val, s); } static void buffer_append_crashmem(struct buffer *buffer, struct kimage *image) { int i; int size; if (image->minik_type == MINIK_V1) { size = 0; for (i = 0; i < image->num_minik_mem; i++) { size += image->reserve_mem[i].size_bytes; } size = size / (1024 * 1024); buffer_append(buffer, " mem=%dM", size); return; } if (image->reserve_mem_dma.size_bytes > 0) { buffer_append(buffer, " memmap="); buffer_append_memparse(buffer, image->reserve_mem_dma.size_bytes); buffer_append(buffer, "@"); buffer_append_memparse(buffer, image->reserve_mem_dma.base_pa); } for (i = 0; i < image->num_minik_mem; i++) { buffer_append(buffer, " memmap="); buffer_append_memparse(buffer, image->reserve_mem[i].size_bytes); buffer_append(buffer, "@"); buffer_append_memparse(buffer, image->reserve_mem[i].base_pa); } } static void string_arg_strip(char *string, const char *arg) { char *s, *s2; s = string; while ((s = strstr(s, arg))) { if (s > string && s[-1] != ' ') continue; s2 = s + strlen(arg); while (*s2 && *s2 != ' ') s2++; while (*s2 == ' ') s2++; memmove(s, s2, strlen(s2) + 1); } } int pimage_create(struct kimage *image) { struct x86_linux_param_header *real_mode; int setup_sects; int command_line_len; int command_line_off; int kern32_size; int setup32_off; char *cmdline; char *start32; unsigned long entry; size_t size; char image_command_line[COMMAND_LINE_SIZE]; struct buffer image_command_line_buffer = { .end = image_command_line + sizeof(image_command_line), }; /* * Prepare the minik command line arguments. */ /* Copy the current kernel's commandline. */ strncpy(image_command_line, saved_command_line, sizeof(image_command_line)); image_command_line[sizeof(image_command_line) - 1] = 0; /* Do not: append " crashkernel=no" * as the commandline may get too big to fit in. * Drop the original parameter instead. */ string_arg_strip(image_command_line, "crashdma="); string_arg_strip(image_command_line, "crashmain="); image_command_line_buffer.tail = image_command_line + strlen(image_command_line); if (image->minik_type == MINIK_V1) { buffer_append(&image_command_line_buffer, " dump_dev=%s maxcpus=1 noapic irqpoll", mkexec_inf.ddev); } else { buffer_append(&image_command_line_buffer, " dump_dev=%s" " dump_pfn=0x%lx" /* BSP causes problems when starting secondary CPU in minik. */ " maxcpus=1" /* FIXME: mkexec/SMP+minik/SMPmaxcpu=1 locks on no timer on 2.6.12 */ " noapic" /* Device-shared interrupts may get stuck. */ " irqpoll" " memmap=exactmap" /* * minik locks up if no 4K page is available below 1MB. * Some untested driver may require some addition low memory pages. * These values are just random choice in the 640KB range. */ " memmap=64K@192K" , mkexec_inf.ddev, /* " dump_dev=%s" */ page_to_pfn(image->dump_header_pages)); /* " dump_pfn=0x%lx" */ } buffer_append_crashmem(&image_command_line_buffer, image); /* Keep 'mkexec_inf.parm' last to make the parameters overridable by user. */ buffer_append(&image_command_line_buffer, " %s", mkexec_inf.parm); #if 0 /* debug */ printk("minik commandline: %s\n", image_command_line); #endif if (image_command_line_buffer.tail >= image_command_line_buffer.end - 1) { /* Re-termination should not be needed here. */ image_command_line_buffer.end[-1] = 0; printk("mkexec: minik commandline too long, the fitted part: %s\n", image_command_line); return -1; } setup_sects = 4; kern32_size = (setup_sects +1) *512; // /* Can not get kernel version.(setup sector has version information.) */ // kernel_version = ((unsigned char *)&header) + 512 + header.kver_addr; /* The x86 code segment */ command_line_off = kern32_size; /* The 32bit entry point */ command_line_len = (image_command_line_buffer.tail + 1) - image_command_line; size = (command_line_off + command_line_len+16-1) & ~(16-1) ; setup32_off = (size + 3) & ~3; /* 4 byte align */ size = setup32_off + setup32_size; image->segment[0].memsz = image->segment[0].bufsz = size; image->segment[0].buf = (char *)((unsigned long)\ kmap(pfn_to_page(image->new_kernel_paddr >> PAGE_SHIFT)) + image->segment[0].mem); real_mode = image->segment[0].buf; cmdline = (char *)image->segment[0].buf + command_line_off; start32 = (char *)image->segment[0].buf + setup32_off; entry = (unsigned long)image->segment[0].mem + setup32_off; memset(image->segment[0].buf, 0, image->segment[0].bufsz); kunmap(pfn_to_page(image->new_kernel_paddr>> PAGE_SHIFT)); /* * Initialize the param_header with bootloader information. */ /* The location of the command line */ real_mode->cl_magic = CL_MAGIC_VALUE; real_mode->cl_offset = command_line_off; // if (header.protocol_version >= 0x0202) { // real_mode->cmd_line_ptr = 0x90000 + command_line_off; // } /* Provide absolute physical address of the commandline, it is not relocated. */ real_mode->cmd_line_ptr = __pa(cmdline); real_mode->heap_end_ptr = image->segment[0].bufsz + 1024; /* The loader type */ real_mode->loader_type = LOADER_TYPE_UNKNOWN; /* The ramdisk */ real_mode->initrd_start = 0; real_mode->initrd_size = 0; /* * Initialize the 32bit start information. */ setup32_regs.eax = 0; /* unused */ setup32_regs.ebx = 0; /* 0 == boot not AP processor start */ setup32_regs.ecx = 0; /* unused */ setup32_regs.edx = 0; /* unused */ setup32_regs.esi = (unsigned long)image->segment[0].mem; /* kernel parameters */ setup32_regs.edi = 0; /* unused */ setup32_regs.esp = (unsigned long)image->segment[0].mem; /* stack, unused */ setup32_regs.ebp = 0; /* unused */ setup32_regs.eip = (unsigned long)image->segment[1].mem; /* kernel entry point */ /* * Copy it all into the startup vector */ strcpy(cmdline, image_command_line); memcpy(start32, setup32_start, setup32_size); /* Fill in the information BIOS calls would normally provide. */ if (setup_linux_parameters(real_mode) < 0) { return -1; } image->start = entry; return 0; } --- NEW FILE: x86-setup-32.S --- /* * arch/i386/kernel/x86-setup-32.S * * mkexec: Linux boots Linux(Mini kernel) * * $Id: x86-setup-32.S,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. */ /* * Some codes were derived from kexec : * * kexec: Linux boots Linux * * Copyright (C) 2003,2004 Eric Biederman (ebi...@xm...) * * 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 (version 2 of the License). * * 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. * * You should have received a copy of the GNU General Public License * along with this program ; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ .data .code32 .globl setup32_start, setup32_end, setup32_size .globl setup32_regs setup32_start: _reloc = . /* Compute where I am running at */ pushl %ebx call 1f 1: popl %ebx subl $(1b - _reloc), %ebx /* align the code, I feel better when word load & store instructions * are aligned. */ nop /* Relocate the code */ addl %ebx, reloc1 - _reloc(%ebx) addl %ebx, reloc2 - _reloc(%ebx) addl %ebx, reloc3 - _reloc(%ebx) popl reloc4 - _reloc(%ebx) pushl %eax movl reloc4 - _reloc(%ebx), %eax addl %eax, ebx - _reloc(%ebx) addl %eax, eip - _reloc(%ebx) addl %eax, esp - _reloc(%ebx) addl %eax, esi - _reloc(%ebx) popl %eax /* Make certain the special registers are in a sane state. * The kernel should have done this but... */ call x86_setup_state /* Setup a gdt that should be preserved */ /* This also acts as a serializing instruction ensuring * my self modifying code works. */ lgdt gdt - _reloc(%ebx) /* load the data segments */ movl $0x18, %eax /* data segment */ movl %eax, %ds movl %eax, %es movl %eax, %ss movl %eax, %fs movl %eax, %gs /* load the code segment */ leal 1f - _reloc(%ebx), %eax pushl $0x10 /* code segment */ pushl %eax /* destination address */ lret 1: /* Load the registers */ movl eax - _reloc(%ebx), %eax movl ecx - _reloc(%ebx), %ecx movl edx - _reloc(%ebx), %edx movl esi - _reloc(%ebx), %esi movl edi - _reloc(%ebx), %edi movl esp - _reloc(%ebx), %esp movl ebp - _reloc(%ebx), %ebp .byte 0x8b, 0x1d # movl ebx, %ebx reloc1: .long ebx - _reloc nop nop .byte 0xff, 0x25 # jmpl *(eip) reloc2: .long eip - _reloc .balign 4 setup32_regs: eax: .long 0x00000000 ebx: .long 0x00000000 ecx: .long 0x00000000 edx: .long 0x00000000 esi: .long 0x00000000 edi: .long 0x00000000 esp: .long 0x00000000 ebp: .long 0x00000000 eip: .long 0x00000000 gdt: /* 0x00 unusable segment so used as the gdt ptr */ .word gdt_end - gdt - 1 reloc3: .long gdt - _reloc .word 0 /* 0x08 dummy */ .word 0x0000, 0x0000, 0x0000, 0x000 /* Documented linux kernel segments */ /* 0x10 4GB flat code segment */ .word 0xFFFF, 0x0000, 0x9A00, 0x00CF /* 0x18 4GB flat data segment */ .word 0xFFFF, 0x0000, 0x9200, 0x00CF /* 0x20 dummy */ .word 0x0000, 0x0000, 0x0000, 0x000 /* 0x28 dummy */ .word 0x0000, 0x0000, 0x0000, 0x000 /* 0x30 dummy */ .word 0x0000, 0x0000, 0x0000, 0x000 /* 0x38 dummy */ .word 0x0000, 0x0000, 0x0000, 0x000 /* 0x40 dummy */ .word 0x0000, 0x0000, 0x0000, 0x000 /* 0x48 dummy */ .word 0x0000, 0x0000, 0x0000, 0x000 /* 0x50 dummy */ .word 0x0000, 0x0000, 0x0000, 0x000 /* 0x58 dummy */ .word 0x0000, 0x0000, 0x0000, 0x000 /* Segments used by the 2.5.x kernel */ /* 0x60 4GB flat code segment */ .word 0xFFFF, 0x0000, 0x9A00, 0x00CF /* 0x68 4GB flat data segment */ .word 0xFFFF, 0x0000, 0x9200, 0x00CF gdt_end: reloc4: .long 0 /* #include "x86-setup-state.S" */ .code32 /* Make certain the special registers are in a sane state. * The kernel should have done this but... */ x86_setup_state: /* Don't modify any registers... */ pushl %eax /* clear special bits in %cr4 */ movl %cr4, %eax andl $0, %eax movl %eax, %cr4 popl %eax ret /* #include "x86-setup-state.S" END */ setup32_end: setup32_size: .long setup32_end - setup32_start --- NEW FILE: mkexec-x86.c --- /* * arch/i386/kernel/mkexec-x86.c * * mkexec: Linux boots Linux(Mini kernel) * * $Id: mkexec-x86.c,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. */ /* * Some codes were derived from kexec : * * kexec: Linux boots Linux * * Copyright (C) 2003,2004 Eric Biederman (ebi...@xm...) * * 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 (version 2 of the License). * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/config.h> #include <linux/stddef.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/fcntl.h> #include <linux/stat.h> #include <linux/ide.h> #include <linux/fs.h> #include <linux/vmalloc.h> #include <linux/mkexec.h> #include <asm/mkexec.h> #include <asm/mkexec-x86.h> #include <asm/x86-linux.h> #define MAX_MEMORY_RANGES 20 #define MAX_LINE 160 #define MKEXEC_READ_BUF_SIZE 2048 static struct memory_range memory_range[MAX_MEMORY_RANGES]; extern struct mexec_mod_t mexec_inf; /* Return a sorted list of memory ranges. */ int get_memory_ranges(struct memory_range **range, int *ranges) { const char iomem[]= "/proc/iomem"; int memory_ranges = 0; char line[MAX_LINE]; char *read_mem, *end_ptr; ssize_t read_size; char *oc, *ic, *line_max; struct file *file = 0; char * tmp = 0; int i; int sts = 0; int next_read; mm_segment_t old_fs = get_fs(); /* get read buffer */ read_mem = vmalloc(MKEXEC_READ_BUF_SIZE); if (read_mem < 0) { printk("mexec_mod: vmalloc NG.\n"); return -1 ; } set_fs(KERNEL_DS); tmp = getname(iomem); if (IS_ERR(tmp)) { printk("mexec_mod: can't open %s.\n", iomem); vfree(read_mem); set_fs(old_fs); return -1 ; } file = filp_open(tmp, O_RDONLY, 0); putname(tmp); if (IS_ERR(file)) { printk("mexec_mod: can't open %s.\n", iomem); vfree(read_mem); set_fs(old_fs); return -1 ; } oc = line; line_max = oc + MAX_LINE; for(i=0; sts != -1;i++){ next_read = 0; memset(read_mem, 0, MKEXEC_READ_BUF_SIZE); if(default_llseek(file, MKEXEC_READ_BUF_SIZE * i, 0) < 0){ printk("default_llseek NG.\n"); read_size = 0; sts = -1; goto err; } if((read_size = vfs_read(file, read_mem, MKEXEC_READ_BUF_SIZE, &file->f_pos)) < 0){ printk("mini-kernel load NG(can't read %s)\n", iomem); printk("--- i=%d read_size=0x%x---\n", i, read_size); sts = -1; goto err; } /* EOF */ if (read_size == 0){ break; } end_ptr = read_mem + read_size; for(ic=read_mem; ; ){ unsigned long long start, end; char *str; int type; int consumed; int count; if (memory_ranges >= MAX_MEMORY_RANGES) break; for (; ; ic++, oc++){ if (end_ptr == ic){ next_read = 1; break; } if (line_max == oc){ printk("%s:too many characters of one line.\n", iomem); sts = -1; goto err; } *oc = *ic; if (*ic=='\0' || *ic==0x0a){ *oc++ = '\0'; ic++; break; } } if(next_read == 1){ break; } count = sscanf(line, "%Lx-%Lx : %n", &start, &end, &consumed); if (count != 2) { continue; } str = line + consumed; end = end + 1; #if 0 printk("%016Lx-%016Lx : %s\n", start, end, str); #endif if (memcmp(str, "System RAM", 10) == 0) { type = RANGE_RAM; } else if (memcmp(str, "reserved", 8) == 0) { type = RANGE_RESERVED; } else if (memcmp(str, "ACPI Tables", 11) == 0) { type = RANGE_ACPI; } else if (memcmp(str, "ACPI Non-volatile Storage", 25) == 0) { type = RANGE_ACPI_NVS; } else { oc = line; continue; } memory_range[memory_ranges].start = start; memory_range[memory_ranges].end = end; memory_range[memory_ranges].type = type; #if 0 printk("*** OK *** %016Lx-%016Lx : %x\n", start, end, type); #endif memory_ranges++; oc = line; } } err: set_fs(old_fs); filp_close(file, NULL); vfree(read_mem); *range = memory_range; *ranges = memory_ranges; return 0; } --- NEW FILE: machine_mkexec.c --- /* * arch/i386/kernel/machine_mkexec.c * * $Id: machine_mkexec.c,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. */ /* * Some codes were derived from kexec(machine_kexec.c) : * * machine_kexec.c - handle transition of Linux booting another kernel * Copyright (C) 2002-2004 Eric Biederman <ebi...@xm...> * * This source code is licensed under the GNU General Public License, * Version 2. See the file COPYING for more details. */ #include <linux/mm.h> #include <asm/pgtable.h> #include <asm/pgalloc.h> #include <asm/mmu_context.h> #include <asm/io.h> #include <asm/apic.h> #include <asm/cpufeature.h> #include <linux/mkexec.h> #include <asm/mkexec-x86.h> static int identity_map_page(unsigned long addr) { int error = 0; pgd_t *dir; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12) pud_t *pud; #endif pmd_t *pmd; pte_t *pte; dir = pgd_offset(&init_mm, addr); spin_lock(&init_mm.page_table_lock); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12) pud = pud_alloc(&init_mm, dir, addr); pmd = pmd_alloc(&init_mm, pud, addr); #else pmd = pmd_alloc(&init_mm, dir, addr); #endif if (pmd == NULL) { error = -ENOMEM; goto out; } pte = pte_alloc_kernel(&init_mm, pmd, addr); if (pte == NULL) { error = -ENOMEM; goto out; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8) set_pte(pte, pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_EXEC)); #else set_pte(pte, pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL)); #endif out: spin_unlock(&init_mm.page_table_lock); return error; } static void set_idt(void *newidt, __u16 limit) { unsigned char curidt[6]; /* ia32 supports unaliged loads & stores */ (*(__u16 *)(curidt)) = limit; (*(__u32 *)(curidt +2)) = (unsigned long)(newidt); __asm__ __volatile__ ( "lidt %0\n" : "=m" (curidt) ); }; static void set_gdt(void *newgdt, __u16 limit) { unsigned char curgdt[6]; /* ia32 supports unaligned loads & stores */ (*(__u16 *)(curgdt)) = limit; (*(__u32 *)(curgdt +2)) = (unsigned long)(newgdt); __asm__ __volatile__ ( "lgdt %0\n" : "=m" (curgdt) ); }; static void load_segments(void) { #define __STRX(X) #X #define STRX(X) __STRX(X) __asm__ __volatile__ ( "\tljmp $"STRX(__KERNEL_CS)",$1f\n" "\t1:\n" "\tmovl $"STRX(__KERNEL_DS)",%eax\n" "\tmovl %eax,%ds\n" "\tmovl %eax,%es\n" "\tmovl %eax,%fs\n" "\tmovl %eax,%gs\n" "\tmovl %eax,%ss\n" ); #undef STRX #undef __STRX } typedef asmlinkage void (*start_new_kernel_t)( unsigned long indirection_page, unsigned long reboot_code_buffer, unsigned long start_address, unsigned int has_pae); const extern unsigned char start_new_kernel[]; extern void start_new_kernel_end(void); const extern unsigned int start_new_kernel_size; /* * Do what every setup is needed on image and the * reboot code buffer to allow us to avoid allocations * later. Currently nothing. */ int machine_mkexec_prepare(struct kimage *image) { return identity_map_page(image->reboot_code_addr); } void machine_mkexec_cleanup(struct kimage *image) { } /* * Do not allocate memory (or fail in any way) in machine_kexec(). * We are past the point of no return, committed to rebooting now. */ void machine_mkexec(struct kimage *image) { start_new_kernel_t rnk; /* Interrupts aren't acceptable while we reboot */ local_irq_disable(); /* switch to an mm where the reboot_code_buffer is identity mapped */ load_cr3(init_mm.pgd); /* The segment registers are funny things, they are * automatically loaded from a table, in memory wherever you * set them to a specific selector, but this table is never * accessed again you set the segment to a different selector. * * The more common model is are caches where the behide * the scenes work is done, but is also dropped at arbitrary * times. * * I take advantage of this here by force loading the * segments, before I zap the gdt with an invalid value. */ load_segments(); /* The gdt & idt are now invalid. * If you want to load them you must set up your own idt & gdt. */ set_gdt(phys_to_virt(0),0); set_idt(phys_to_virt(0),0); /* now call it */ rnk = (start_new_kernel_t)image->reboot_code_addr; (*rnk)(image->new_kernel_paddr, image->reboot_code_addr, image->start+image->new_kernel_paddr, cpu_has_pae); } --- NEW FILE: minik_dump.c --- /* * arch/i386/kernel/minik_dump.c * * $Id: minik_dump.c,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <linux/init.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/smp.h> #include <linux/irq.h> #include <linux/time.h> #include <linux/sched.h> #include <linux/vmalloc.h> #include <linux/mm.h> #include <linux/mmzone.h> #include <linux/delay.h> #include <linux/ptrace.h> #include <linux/utsname.h> #include <linux/mkexec.h> #include <linux/minik_param.h> #include <linux/cpus.h> #include <asm/processor.h> #include <asm/smp.h> #include <asm/e820.h> #include <asm/hardirq.h> #include <asm/nmi.h> #include <asm/apic.h> #include <asm/io_apic.h> #include <asm/minik_dump.h> static struct dump_header *dhp; extern void mkexec_exec(void); static void mem_seg_init(struct mem_seg *mem_segp) { pg_data_t *pgdat; int i; unsigned long avoid_pfn = 0; mem_segp->page_size = PAGE_SIZE; /* XXX: intension: avoid reserved area around 4GB (is there write only area ?) */ /* this code is uncertain for NUMA */ for (i = 0; i < e820.nr_map; i++) { if (e820.map[i].type == E820_RESERVED && e820.map[i].addr > 0xfffff) { avoid_pfn = e820.map[i].addr >> PAGE_SHIFT; break; } } pgdat = pgdat_list; i = 0; if (avoid_pfn && avoid_pfn < pfn_pgdat(pgdat) + size_pgdat(pgdat)) { /* assume start to 0 */ mem_segp->seg_list[i].seg_start_pfn = 0; mem_segp->seg_list[i].seg_size_pfn = avoid_pfn; i++; if (size_pgdat(pgdat) > 0x100000UL) { /* over 4GB */ mem_segp->seg_list[i].seg_start_pfn = 0x100000UL; mem_segp->seg_list[i].seg_size_pfn = size_pgdat(pgdat) - 0x100000UL; i++; } } else { mem_segp->seg_list[i].seg_start_pfn = 0; mem_segp->seg_list[i].seg_size_pfn = size_pgdat(pgdat); i++; } for (pgdat = next_pgdat(pgdat); pgdat && i < MAX_MEM_SEG; pgdat = next_pgdat(pgdat), i++) { mem_segp->seg_list[i].seg_start_pfn = pfn_pgdat(pgdat); mem_segp->seg_list[i].seg_size_pfn = size_pgdat(pgdat); } mem_segp->seg_num = i; } /* * init_dump_header called when dump-mini-kernel load. */ void init_dump_header(struct kimage *image) { unsigned long *addrp; long size; int i; if (image->minik_type == MINIK_V1) { dhp = (struct dump_header *)(__va(image->reserve_mem[0].base_pa) + PAGE_SIZE * 2); } else { dhp = (struct dump_header *)page_address(image->dump_header_pages); } strncpy(dhp->dh_version.dv_magic, DUMP_MAGIC, DUMP_MAGIC_LEN); dhp->dh_version.dv_version = DUMP_VERSION; dhp->dh_version.dv_arch = DUMP_ARCH_I386; /* dv_unique set later */ /* dh_dump_cpu N/A */ memset(dhp->dh_tasks, 0, sizeof(dhp->dh_tasks)); memset(dhp->dh_regs, 0, sizeof(dhp->dh_regs)); memset(dhp->dh_panic_string, 0, sizeof(dhp->dh_panic_string)); /* dh_time N/A */ dhp->dh_utsname = system_utsname; mem_seg_init((void *)((u8 *)dhp + PAGE_SIZE)); if (image->minik_type == MINIK_V1) { addrp = (unsigned long *)(__va(image->reserve_mem[0].base_pa) + PAGE_SIZE); for (i = 0; i < image->num_minik_mem; i++) { size = image->reserve_mem[i].size_bytes; /* must be multiple 4MB ! */ while (size > 0) { *addrp = image->reserve_mem[i].base_pa + image->reserve_mem[i].size_bytes - size; addrp++; size -= MINIK_SEG_SIZE; } /* ODA: should check addrp range */ } *addrp = 0; } } /* * get current context * (copy from LKCD) */ static inline void get_current_regs(struct pt_regs *regs) { __asm__ __volatile__("movl %%ebx,%0" : "=m"(regs->ebx)); __asm__ __volatile__("movl %%ecx,%0" : "=m"(regs->ecx)); __asm__ __volatile__("movl %%edx,%0" : "=m"(regs->edx)); __asm__ __volatile__("movl %%esi,%0" : "=m"(regs->esi)); __asm__ __volatile__("movl %%edi,%0" : "=m"(regs->edi)); __asm__ __volatile__("movl %%ebp,%0" : "=m"(regs->ebp)); __asm__ __volatile__("movl %%eax,%0" : "=m"(regs->eax)); __asm__ __volatile__("movl %%esp,%0" : "=m"(regs->esp)); __asm__ __volatile__("movw %%ss, %%ax;" :"=a"(regs->xss)); __asm__ __volatile__("movw %%cs, %%ax;" :"=a"(regs->xcs)); __asm__ __volatile__("movw %%ds, %%ax;" :"=a"(regs->xds)); __asm__ __volatile__("movw %%es, %%ax;" :"=a"(regs->xes)); __asm__ __volatile__("pushfl; popl %0" :"=m"(regs->eflags)); regs->eip = (unsigned long)current_text_addr(); } #ifdef MKEXEC_NO_PATCH #ifdef CONFIG_X86_IO_APIC extern void disable_IO_APIC(void); extern spinlock_t ioapic_lock; #endif #ifdef CONFIG_X86_LOCAL_APIC void disconnect_bsp_APIC(void); #endif static void mkexecreboot(void) { #if defined(CONFIG_X86_LOCAL_APIC) if (cpu_has_apic) { disable_local_APIC(); } #endif #if defined(CONFIG_X86_IO_APIC) spin_lock_init(&ioapic_lock); /* force to lock success */ disable_IO_APIC(); #elif defined(CONFIG_X86_LOCAL_APIC) disconnect_bsp_APIC(); #endif mkexec_exec(); } void mkdump_send_nmi(void) { unsigned int cfg; /* * if there are no other CPUs in the system then we get an APIC send * error if we try to broadcast, thus avoid sending IPIs in this case. */ if (!(num_online_cpus() > 1)) return; /* * Wait for idle. */ apic_wait_icr_idle(); /* * No need to touch the target chip field */ cfg = APIC_DM_FIXED | APIC_DEST_ALLBUT | APIC_DM_NMI | APIC_DEST_LOGICAL; /* * Send the IPI. The write to APIC_ICR fires this off. */ apic_write_around(APIC_ICR, cfg); return; } #else /* MKEXEC_NO_PATCH */ #ifdef CONFIG_X86_IO_APIC static void ioapic_mkexec_restore_once(void) { static int tried[NR_CPUS]; int cpu = get_processor_id(); /* We may crash inside: ioapic_mkexec_restore() */ if (tried[cpu]) return; tried[cpu] = 1; spin_lock_init(&ioapic_lock); /* Force success of locking it inside. */ ioapic_mkexec_restore(); /* errors ignored */ } #endif #ifdef CONFIG_X86_LOCAL_APIC void lapic_mkexec_restore_once(void) { static int tried[NR_CPUS]; int cpu = get_processor_id(); if (!cpu_has_apic) return; /* We may crash inside: lapic_mkexec_restore() */ if (tried[cpu]) return; tried[cpu] = 1; lapic_mkexec_restore(); /* errors ignored */ } #endif static void mkexecreboot(void) { /* Do not: disable_IO_APIC(); * or: disable_local_APIC(); * as we may not imitate the BIOS legacy IRQ0 settings properly. * Later minik may hang-up on: Calibrating delay loop... */ #ifdef CONFIG_X86_IO_APIC ioapic_mkexec_restore_once(); #endif /* CONFIG_X86_IO_APIC */ #ifdef CONFIG_X86_LOCAL_APIC lapic_mkexec_restore_once(); #endif mkexec_exec(); } #endif /* MKEXEC_NO_PATCH */ #ifdef CONFIG_SMP static atomic_t waiting_for_dump_ipi; static int save_done[NR_CPUS]; static int reboot_cpu = 0; void mkdump_send_nmi(void); static void wait_and_mkexecreboot(void) { int i; for (i = 0; i < 1000000000; i++) { if (atomic_read(&waiting_for_dump_ipi) == 0) { break; } } mkexecreboot(); } static int mkdump_nmi_callback(struct pt_regs *regs, int fcpu) { /* 'fcpu' came from: do_nmi()->smp_processor_id() */ int cpu = get_processor_id(); if (save_done[cpu]) { return 1; /* anyway now in dump, suppress default nmi handler */ } dhp->dh_tasks[cpu] = (cpu == fcpu ? (unsigned long)current : 0); dhp->dh_regs[cpu] = *regs; if (!(regs->xcs & 3)) { /* IA-32 Intel(R) Architecture Software Developer's Manual, Volume 3: System Programming Guide * <http://www.intel.com/design/pentium4/manuals/253668.htm> * Chapter 5.12.1 Exception- or Interrupt-Handler Procedures: * No ss/esp saved on stack on no privilege change. */ /* AMD64 Architecture Programmer's Manual Volume 2: System Programming * <http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/24593.pdf> * Chapter 8.9.3 Interrupt Stack Frame: * It does not apply to x86_64 as ss/rsp is always saved there. */ dhp->dh_regs[cpu].esp = (unsigned long) (®s->esp); dhp->dh_regs[cpu].xss = __KERNEL_DS; } save_done[cpu] = 1; atomic_dec(&waiting_for_dump_ipi); if (cpu == reboot_cpu) { wait_and_mkexecreboot(); } else { stop_this_cpu_safe(NULL); } return 1; } static void stop_other_cpus(int cpu) { int i; int other_cpus = num_online_cpus() - 1; if (other_cpus < 1) { /* Other CPUs are not online and we do not need to stop them. * At least as long as 'cpu_online_map' is valid. */ return; } /* always boot from 0. but if 0 is not online... */ if (!cpu_isset(reboot_cpu, cpu_online_map)) { reboot_cpu = cpu; } atomic_set(&waiting_for_dump_ipi, other_cpus); for (i = 0; i < NR_CPUS; i++) { save_done[i] = 0; } set_nmi_callback(mkdump_nmi_callback); wmb(); mkdump_send_nmi(); if (cpu == reboot_cpu) { wait_and_mkexecreboot(); } else { stop_this_cpu_safe(NULL); } } #endif /* * start_dump called when dump occur. * save context, stop other cpus and boot mini kernel */ void start_dump(char *panic_str, struct pt_regs *regs, int cpu) { struct pt_regs cur_reg; int fcpu = smp_processor_id(); if (regs == NULL) { get_current_regs(&cur_reg); } else { cur_reg = *regs; /* IA-32 Intel(R) Architecture Software Developer's Manual, Volume 3: System Programming Guide * <http://www.intel.com/design/pentium4/manuals/253668.htm> * Chapter 5.12.1 Exception- or Interrupt-Handler Procedures: * No ss/esp saved on stack on no privilege change. */ /* AMD64 Architecture Programmer's Manual Volume 2: System Programming * <http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/24593.pdf> * Chapter 8.9.3 Interrupt Stack Frame: * It does not apply to x86_64 as ss/rsp is always saved there. */ if (!(regs->xcs & 3)) { cur_reg.esp = (unsigned long) (®s->esp); cur_reg.xss = __KERNEL_DS; } } dhp->dh_version.dv_unique = (u32)xtime.tv_sec; dhp->dh_dump_cpu = cpu; #if !defined(BACKPORT_24) dhp->dh_time = xtime; #else dhp->dh_time.tv_sec = xtime.tv_sec; dhp->dh_time.tv_nsec = 1000 * xtime.tv_usec; #endif dhp->dh_tasks[cpu] = (cpu == fcpu ? (unsigned long)current : 0); dhp->dh_regs[cpu] = cur_reg; strncpy(dhp->dh_panic_string, panic_str, DUMP_PANIC_LEN); #ifdef CONFIG_SMP /* stop_other_cpus() can return. */ stop_other_cpus(cpu); #endif mkexecreboot(); } --- NEW FILE: start_new_kernel.S --- /* * arch/i386/kernel/start_new_kernel.S * * $Id: start_new_kernel.S,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. */ /* * Some codes were derived from kexec(relocate_kernel.S) : * * relocate_kernel.S - put the kernel image in place to boot * Copyright (C) 2002-2003 Eric Biederman <ebi...@xm...> * * This source code is licensed under the GNU General Public License, * Version 2. See the file COPYING for more details. */ #include <linux/linkage.h> /* * Must be relocatable PIC code callable as a C function, that once * it starts can not use the previous processes stack. */ .globl start_new_kernel start_new_kernel: /* read the arguments and say goodbye to the stack */ movl 4(%esp), %ebx /* new address */ movl 8(%esp), %ebp /* reboot_code_buffer */ movl 12(%esp), %edx /* start address */ movl 16(%esp), %ecx /* cpu_has_pae */ /* zero out flags, and disable interrupts */ pushl $0 popfl /* set a new stack at the bottom of our page... */ lea 4096(%ebp), %esp /* store the parameters back on the stack */ pushl %edx /* store the start address */ /* Set cr0 to a known state: * 31 0 == Paging disabled * 18 0 == Alignment check disabled * 16 0 == Write protect disabled * 3 0 == No task switch * 2 0 == Don't do FP software emulation. * 0 1 == Proctected mode enabled */ movl %cr0, %eax andl $~((1<<31)|(1<<18)|(1<<16)|(1<<3)|(1<<2)), %eax orl $(1<<0), %eax movl %eax, %cr0 /* clear cr4 if applicable */ testl %ecx, %ecx jz 1f /* Set cr4 to a known state: * Setting everything to zero seems safe. */ movl %cr4, %eax andl $0, %eax movl %eax, %cr4 jmp 1f 1: /* Flush the TLB (needed?) */ xorl %eax, %eax movl %eax, %cr3 /* set all of the registers to known values */ /* leave %esp alone */ xorl %eax, %eax /* xorl %ebx, %ebx *//* new address */ xorl %ecx, %ecx xorl %edx, %edx xorl %esi, %esi xorl %edi, %edi xorl %ebp, %ebp ret start_new_kernel_end: .globl start_new_kernel_size start_new_kernel_size: .long start_new_kernel_end - start_new_kernel |
From: Itsuro O. <od...@us...> - 2006-02-14 05:30:36
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/kernel In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12378/3.0/2.6/kernel Added Files: Makefile Makefile.24 Makefile.26 Makefile.base minik_dump.c mkexec_main.c mklds Log Message: register for 3.0: based on 2.1 mkexec-2_0-linux-2_6-2_r --- NEW FILE: Makefile.26 --- # # kernel/Makefile.26 # # Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. # Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. # # This file is part of Mkdump. # # Mkdump 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 (version 2 of the License). # # Mkdump 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. # # You should have received a copy of the GNU General Public License # along with Mkdump; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # #ARCH = i386 KMODSRC := mkexec.c KMODOBJ := $(KMODSRC:.c=.o) ifeq ($(ARCH),i386) KARCHOBJ := ../arch/i386/kernel/machine_mkexec.o ../arch/i386/kernel/mkexec-vmlinux.o ../arch/i386/kernel/minik_dump.o ../arch/i386/kernel/start_new_kernel.o ../arch/i386/kernel/x86-setup-32.o endif ifeq ($(ARCH),x86_64) KARCHOBJ := ../arch/x86_64/kernel/machine_mkexec.o ../arch/x86_64/kernel/mkexec-vmlinux.o ../arch/x86_64/kernel/minik_dump.o ../arch/x86_64/kernel/start_new_kernel.o ../arch/x86_64/kernel/x86_64-setup-32.o endif EXTRA_LDFLAGS := -T $(PWD)/sym.lds mkexec-objs:= mkexec_main.o minik_dump.o $(KARCHOBJ) KMOD_KO := $(KMODOBJ:.o=.ko) ifneq ($(KERNELRELEASE),) obj-m := $(KMODOBJ) else include Makefile.base endif --- NEW FILE: mklds --- #!/bin/bash # # kernel/mklds # # Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. # Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. # # This file is part of Mkdump. # # Mkdump 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 (version 2 of the License). # # Mkdump 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. # # You should have received a copy of the GNU General Public License # along with Mkdump; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # SYSTEMMAP=$1 IMPORT_FILE=$2 SYMS=`grep '^IMPORT_SYMBOL' $IMPORT_FILE | sed -r 's/^IMPORT_SYMBOL\((\w+)\)\;/\1/'` for i in $SYMS do ADDR=`cat $SYSTEMMAP | awk '$3=="'$i'"{ print $1 }'` echo "$i = 0x$ADDR ;" done --- NEW FILE: Makefile.24 --- # # kernel/Makefile.24 # # Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. # Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. # # This file is part of Mkdump. # # Mkdump 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 (version 2 of the License). # # Mkdump 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. # # You should have received a copy of the GNU General Public License # along with Mkdump; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # Echo Make Variable. Use via: make emv=CFLAGS ifneq ($(emv),) emv: @echo $($(emv)) endif # We are not interedted in failed products .DELETE_ON_ERROR: IFLAGS += -I../include #ARCH = i386 #ARCH = x86_64 ifeq ($(ARCH),i386) KARCHOBJ := \ ../arch/i386/kernel/machine_mkexec.o \ ../arch/i386/kernel/mkexec-vmlinux.o \ ../arch/i386/kernel/minik_dump.o \ ../arch/i386/kernel/start_new_kernel.o \ ../arch/i386/kernel/x86-setup-32.o endif ifeq ($(ARCH),x86_64) KARCHOBJ := \ ../arch/x86_64/kernel/machine_mkexec.o \ ../arch/x86_64/kernel/mkexec-vmlinux.o \ ../arch/x86_64/kernel/minik_dump.o \ ../arch/x86_64/kernel/start_new_kernel.o \ ../arch/x86_64/kernel/x86_64-setup-32.o endif KM_OBJS = mkexec_main.o minik_dump.o $(KARCHOBJ) mkexec-objs := $(KM_OBJS) # TOPDIR := /usr/src/linux-2.4 #include Make.local ifeq ($(TOPDIR),) $(error TOPDIR must be specified) endif KMODOBJ = mkexec.o #export TOPDIR SOURCEDIR = $(TOPDIR) PWD := $(shell /bin/pwd) EXTRA_CFLAGS += $(CPPFLAGS) $(IFLAGS) $(MDFLAGS) # Add TOPDIR/include to 'standard' to decrease dependencies output EXTRA_CFLAGS += -isystem $(TOPDIR)/include OBJDIR=. # obj-m is a keyword for Linux Rules.make obj-m = $(KMODOBJ) DEPS = $(patsubst %.o, %.d, $(obj-m)) default: all # In Rules.make there is a tricky $(shell ... pathdown) function # that may break, are caused ugly warning, if TOPDIR is not # defined as environment variable. # This is the reason of artifical recursion that we make here. ifeq ($(MK_RECURSE),) # Any nicer way ? # THIS_MAKEFILE = Makefile.24 THIS_MAKEFILE = Makefile all install: $(MAKE) -w -f $(THIS_MAKEFILE) MK_RECURSE=1 EXTRA_CFLAGS="$(EXTRA_CFLAGS)" $@ else # Set CONFIG_SHELL for the sake of Rules.make's MOD_DESTDIR definition CONFIG_SHELL ?= /bin/bash include $(TOPDIR)/Rules.make all: $(MAKE) -w -C $(TOPDIR) modules SUBDIRS=$(PWD) # Explicitly empty-set MOD_DESTDIR to avoid Rules.make's crappy pathdown.sh install: $(MAKE) -w -C $(TOPDIR) modules_install SUBDIRS=$(PWD) \ INSTALL_MOD_PATH=$(INSTALL_MOD_PATH) \ MOD_DESTDIR= endif $(KMODOBJ): $(KM_OBJS) sym.lds $(LD) -r -o $@ $(KM_OBJS) -T sym.lds sym.lds: ../include/asm/mkexec_import.h ./mklds $(TOPDIR)/System.map ../include/asm/mkexec_import.h > sym.lds clean: rm -f $(obj-m) $(DEPS) rm -f $(KM_OBJS) rm -f sym.lds debug: @echo makevar: TOPDIR=$(TOPDIR) @echo envvar: TOPDIR=$$TOPDIR @echo ALL_MOBJS=$(ALL_MOBJS) @echo CONFIG_SHELL=$(CONFIG_SHELL) @echo CFLAGS=$(CFLAGS) --- NEW FILE: Makefile --- # # kernel/Makefile # # Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. # Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. # # This file is part of Mkdump. # # Mkdump 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 (version 2 of the License). # # Mkdump 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. # # You should have received a copy of the GNU General Public License # along with Mkdump; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # ARCH = i386 KTYPE = 26 TOPDIR = /home/src/linux-2.6.12-mkexec-v2-update THISDIR = /home/src/mkdump-v2.0/mkexec-module-2.1/kernel KVER = 2.6.12-mkexec ifeq ($(KTYPE),26) include $(THISDIR)/Makefile.26 endif ifeq ($(KTYPE),24) export TOPDIR include $(THISDIR)/Makefile.24 endif --- NEW FILE: Makefile.base --- # # kernel/Makefile.base # # Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. # Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. # # This file is part of Mkdump. # # Mkdump 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 (version 2 of the License). # # Mkdump 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. # # You should have received a copy of the GNU General Public License # along with Mkdump; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # CFLAGS= CC= gcc LD= ld #KVER= 2.6.12-mkexec-v2 KDIR= $(TOPDIR) SBINDIR= /usr/sbin KMODDIR= /lib/modules/$(KVER) ARCHDIR= arch/$(ARCH)/kernel PWD= $(shell pwd) MKEXECVER= 0.0.1 all: build build: sym.lds kmodules kmodules: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules sym.lds: ./mklds $(KDIR)/System.map ../include/asm/mkexec_import.h > sym.lds install: kmodules [ -d $(KMODDIR)/kernel/$(ARCHDIR) ] || \ mkdir -p $(KMODDIR)/kernel/$(ARCHDIR) for p in $(KMOD_KO); do \ install -c -m 644 $$p $(KMODDIR)/kernel/$(ARCHDIR)/$$p; \ done uninstall: for p in $(KMOD_KO); do \ rm -f $(KMODDIR)/kernel/$(ARCHDIR)/$$p; \ done clean : -rm -rf $(KMOD_KO) *.o .?*.cmd ?*.mod.c core .tmp_versions ../$(ARCHDIR)/*.o ../$(ARCHDIR)/.?*.cmd ../$(ARCHDIR)/?*.mod.c sym.lds --- NEW FILE: minik_dump.c --- /* * kernel/minik_dump.c * * $Id: minik_dump.c,v 1.1 2006/02/14 05:30:27 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <linux/init.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/smp.h> #include <linux/time.h> #include <linux/sched.h> #include <linux/vmalloc.h> #include <linux/mm.h> #include <linux/mmzone.h> #include <linux/ptrace.h> #include <linux/utsname.h> #include <linux/reboot.h> #include <linux/delay.h> #include <linux/mkexec.h> #include <linux/minik_param.h> #include <linux/cpus.h> #include <asm/processor.h> #include <asm/e820.h> #include <asm/hardirq.h> #include <asm/nmi.h> #include <asm/minik_dump.h> /* * start_dump() may crash and we get called again. * It occurs at least from: lapic_mkexec_restore() */ #define LOOPING_MAX 5 extern void (*do_dump_func)(char *, struct pt_regs *); static atomic_t minik_dump_sem = ATOMIC_INIT(1); static int minik_dump_cpu = NR_CPUS; static int looping_count = 0; void do_minik_dump(char *panic_str, struct pt_regs *regs) { int cpu; local_irq_disable(); /* turn off interrupt from now */ bust_spinlocks(1); /* avoid deadlock of printk */ cpu = get_processor_id(); /* check nested dump call */ if (atomic_dec_and_test(&minik_dump_sem)) { /* OK. first call */ minik_dump_cpu = cpu; } else { if (minik_dump_cpu == cpu) { looping_count++; printk("minik: Dump called by the dump routine (looped %d times, max is %d):\n", looping_count, LOOPING_MAX); dump_stack(); if (looping_count >= LOOPING_MAX) { printk("minik: Giving up.\n"); machine_restart(NULL); /* NOTREACHED */ } } else { printk("minik: Dump called by another cpu(%d)\n", cpu); for (;;) { cpu_relax(); } } } printk("minik: Mini Kernel Dump Start. dump cpu = %d\n", cpu); start_dump(panic_str, regs, cpu); /* defined in each arch */ /* not return */ } static void do_minik_netdump(struct pt_regs *regs) { do_minik_dump("do_minik_dump", regs); } void minik_dump_init(struct kimage *image) { init_dump_header(image); #ifdef MKEXEC_NO_PATCH /* only support RHEL currently */ netdump_func = do_minik_netdump; #else do_dump_func = do_minik_dump; #endif } --- NEW FILE: mkexec_main.c --- /* * kernel/mkexec_main.c * * mkexec: Linux boots Linux(Mini kernel) * * $Id: mkexec_main.c,v 1.1 2006/02/14 05:30:27 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. */ /* * Some codes were derived from kexec : * * kexec: Linux boots Linux * * Copyright (C) 2003,2004 Eric Biederman (ebi...@xm...) * * 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 (version 2 of the License). * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/config.h> #include <linux/module.h> #include <linux/stddef.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/stat.h> #include <linux/fcntl.h> #include <linux/proc_fs.h> #include <linux/stat.h> #include <linux/file.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/fs.h> #include <linux/version.h> #include <linux/compile.h> #include <linux/spinlock.h> #include <linux/smp_lock.h> #include <linux/list.h> #include <linux/mm.h> #include <linux/highmem.h> #include <linux/bootmem.h> #include <asm/page.h> #include <asm/uaccess.h> #include <asm/setup.h> #include <linux/mkexec.h> #include <asm/mkexec.h> #include <linux/minik_param.h> #include <asm/minik_dump.h> #include <asm/io.h> static void kimage_copy_reboot_code_pages(struct kimage *image); static int kimage_load(struct kimage *image); extern unsigned long kallsyms_lookup_name(const char *name); typedef struct crashmem *(crashmem_get_t)(int); static int kimage_alloc_reserve(struct kimage *image) { crashmem_get_t *crashmemget; /* ODA: header def minaosi */ struct crashmem *crashmem; /* ODA: header def minaosi */ #ifdef BACKPORT_24 if ((crashmemget = crashmem_get) == 0) { return -ENOMEM; } #else if ((crashmemget = (crashmem_get_t *)kallsyms_lookup_name("crashmem_get")) == 0) { return -ENOMEM; } #endif crashmem = crashmemget(1); if (crashmem && crashmem->size_bytes > 0) { image->reserve_mem_dma.base_pa = crashmem->base_pa; image->reserve_mem_dma.size_bytes = crashmem->size_bytes; } crashmem = crashmemget(0); if (crashmem && crashmem->size_bytes > 0) { image->reserve_mem[0].base_pa = crashmem->base_pa; image->reserve_mem[0].size_bytes = crashmem->size_bytes; } else { return -ENOMEM; } image->num_minik_mem = 1; image->new_kernel_paddr = image->reserve_mem[0].base_pa; /* ODA: common? */ image->reboot_code_addr = image->new_kernel_paddr; /* ODA: common? */ return 0; } static int kimage_alloc_new(struct kimage *image) { int num_seg, order; struct page *pages; int i; if ((mkexec_inf.mem & MINIK_SEG_MASK) != 0 || mkexec_inf.mem > MAX_MINIK_MEM_SEG * MINIK_SEG_SIZE) { return -EINVAL; }/* ODA: x86_64 ?? */ num_seg = mkexec_inf.mem >> MINIK_SEG_SHIFT; order = get_order(MINIK_SEG_SIZE); for (i = 0; i < num_seg; i++) { if (!(pages = alloc_pages(GFP_KERNEL, order))) { return -ENOMEM; } image->reserve_mem[i].base_pa = (unsigned long)(page_to_pfn(pages) << PAGE_SHIFT); image->reserve_mem[i].size_bytes = MINIK_SEG_SIZE; image->reserve_mem[i].pages = pages; image->reserve_mem[i].order = order; } image->num_minik_mem = num_seg; image->new_kernel_paddr = image->reserve_mem[0].base_pa; /* ODA: common? */ image->reboot_code_addr = image->new_kernel_paddr; /* ODA: common? */ return 0; } static int kimage_alloc(struct kimage *image) { int result; if (kimage_alloc_reserve(image) != 0 && (result = kimage_alloc_new(image)) != 0) { return result; } /* two pages: dump header + mem_seg */ image->dump_header_pages = alloc_pages(GFP_KERNEL, 1); if (!image->dump_header_pages) { return -ENOMEM; } image->nr_segments = 2; image->segment[0].mem = (void *)0x90000; /* setup */ image->segment[1].mem = (void *)0x100000; /* kernel 1MB */ // image->segment[2].mem = (void *)0x800000; /* initrd 8MB */ return 0; } static void kimage_copy_reboot_code_pages(struct kimage *image) { char *ptr ; /* copy it out */ ptr = (char *)kmap(pfn_to_page(image->reboot_code_addr >> PAGE_SHIFT)); memcpy(ptr, start_new_kernel, start_new_kernel_size); kunmap(pfn_to_page(image->reboot_code_addr >> PAGE_SHIFT)); } static int kimage_check(struct kimage *image) { if (image->segment[1].bufsz < MINIK_SIGNATURE_OFFSET + strlen(MINIK_SIGNATURE_HEAD)) { printk("mkexec: Loaded image minik is too small (%lu bytes)!\n", (unsigned long)image->segment[1].bufsz); return -EINVAL; } if (!memcmp((u8 *)image->segment[1].buf + MINIK_SIGNATURE_OFFSET, MINIK_SIGNATURE_HEAD, strlen(MINIK_SIGNATURE_HEAD))) { image->minik_type = MINIK_V2; } return 0; } static int kimage_load(struct kimage *image) { loff_t file_size; int read_size; struct file *file; int result = 0; mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); file = filp_open(mkexec_inf.path, O_RDONLY, 0); if (IS_ERR(file)) { printk("mkexec: can't open %s\n", mkexec_inf.path); return -1; } image->segment[1].buf = __va(image->new_kernel_paddr + image->segment[1].mem); file_size = file->f_dentry->d_inode->i_size; if (image->reserve_mem[0].size_bytes < file_size+4) { printk("mkexec: Trying to load too big kernel image" " (file=%lld bytes, /proc/mkexec/mem=%lu bytes)\n", (long long)file_size, image->reserve_mem[0].size_bytes); result = -1; goto out; } if ((read_size = kernel_read(file, 0, image->segment[1].buf, file_size+4)) < 0) { printk("mkexec: mini-kernel read NG(%d): %s\n", read_size, mkexec_inf.path); result = -1; goto out; } if (file_size != read_size){ printk("mkexec: read_size is not file_size. read_size=%d, file_size=%lld\n", read_size, (long long)file_size); result = -1; goto out; } image->segment[1].bufsz = image->segment[1].memsz = file_size; result = kimage_check(image); out: set_fs(old_fs); filp_close(file, NULL); return result; } static int kimage_attr_prot(struct kimage *image, pgprot_t prot) { int err = 0; int numpages, i; struct page *page; return 0; /* not support yet */ if (!image){ return 0; } for (i = 0; i < image->num_minik_mem; i++) { numpages = image->reserve_mem[i].size_bytes >> PAGE_SHIFT; page = pfn_to_page(image->reserve_mem[i].base_pa >> PAGE_SHIFT); // if (i == 0 && image->minik_type == MINIK_V1) { // numpages -= 3; // page += 3; // } err = change_page_attr(page, numpages, prot); if (err) { printk("mkexec: Error setting minik protection (err=%d)!\n", err); break; } } global_flush_tlb(); return err; } static void kimage_free(struct kimage *image) { int i; if (!image){ return; } for (i = 0; i < image->num_minik_mem; i++) { if (image->reserve_mem[i].pages) { __free_pages(image->reserve_mem[i].pages, image->reserve_mem[i].order); } } if (image->dump_header_pages) { __free_pages(image->dump_header_pages, 1); } for (i = 0; i < image->num_control_page; i++) { __free_pages(image->control_page[i], 0); } kfree(image); } extern void minik_dump_init(struct kimage *kimage); struct kimage *mkexec_image = 0; static int mkexec_ddev_check(/* const */ char *ddev_string) { int dump_dev; unsigned long pages_system; unsigned long pages_ddev; struct block_device *bdev; pg_data_t *pgdat; int err; if (1 != get_option(&ddev_string, &dump_dev)) { printk(KERN_ERR "mkexec: Dump device id not a single number!\n"); return -EINVAL; } #ifdef BACKPORT_24 bdev = bdget(convert_old_dev(dump_dev)); #else bdev = bdget(dump_dev); #endif if (bdev == NULL) { printk(KERN_ERR "mkexec: Dump device id 0x%x not an existing device!\n", (unsigned)dump_dev); return -EINVAL; } #ifdef BACKPORT_24 err = blkdev_get(bdev, 0, O_RDWR, 0); #else err = blkdev_get(bdev, 0, O_RDWR); #endif if (err) { printk("mkexec: Dump device id 0x%x blkdev_get() error %d\n", (unsigned)dump_dev, err); /* No bdput(bdev); here. */ return -EINVAL; } pages_ddev = bdev->bd_inode->i_size >> PAGE_SHIFT; #ifdef BACKPORT_24 blkdev_put(bdev, 0); #else blkdev_put(bdev); #endif pages_system = 3; /* dump header pages */ for (pgdat = pgdat_list; pgdat; pgdat = next_pgdat(pgdat)) { pages_system += size_pgdat(pgdat); } if (pages_system > pages_ddev) { printk(KERN_ERR "mkexec: Dump device id 0x%x is too small (device = %lu pages, RAM = %lu pages)!\n", (unsigned)dump_dev, pages_ddev, pages_system); return -EINVAL; } return 0; } int mkexec_load(void) { struct kimage *image; int result; if ((image = kmalloc(sizeof(*image), GFP_KERNEL)) == NULL) { return -ENOMEM; } memset(image, 0, sizeof(*image)); if ((result = kimage_alloc(image)) != 0) { goto out; } if ((result = kimage_load(image)) != 0) { goto out; } if ((result = pimage_create(image)) != 0) { goto out; } if ((result = machine_mkexec_prepare(image)) != 0) { goto out; } kimage_copy_reboot_code_pages(image); minik_dump_init(image); if ((result = kimage_attr_prot(image, PAGE_KERNEL_RO)) != 0) { goto out; } image = xchg(&mkexec_image, image); out: (void)kimage_attr_prot(image, PAGE_KERNEL); kimage_free(image); return result; } int mkexec_exec(void) { struct kimage *image; image = xchg(&mkexec_image, 0); if (!image) { return -EINVAL; } printk(KERN_EMERG "Starting mini kernel\n"); machine_mkexec(image); return -1; } int mkexec_unload(void) { struct kimage *image; #ifdef MKEXEC_NO_PATCH /* only support RHEL currently */ cmpxchg(&netdump_func, (unsigned long)do_minik_dump, (unsigned long)NULL); #else cmpxchg(&do_dump_func, (unsigned long)do_minik_dump, (unsigned long)NULL); #endif image = xchg(&mkexec_image, 0); if (!image) { (void)kimage_attr_prot(image, PAGE_KERNEL); kimage_free(image); } return 0; } /* * mkexec module and /proc interface */ /* * module informations */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("C.Morita"); MODULE_DESCRIPTION("Mini Kernel Exec Module"); char mkexec_proc_base[] = "mkexec"; char mkexec_proc_ddev[] = "mkexec/dumpdev"; char mkexec_proc_mem[] = "mkexec/mem"; char mkexec_proc_stats[] = "mkexec/stats"; char mkexec_proc_path[] = "mkexec/path"; char mkexec_proc_parm[] = "mkexec/parameter"; mkexec_mod_t mkexec_inf; static ssize_t mkexec_proc_read(char __user *ubuf, char *src, size_t cnt, loff_t *ppos) { char tmp_buf[MKEXEC_MOD_MAXLEN]; int len = strlen(src); if (*ppos != 0 || cnt < len + 1) { /* must read at once */ return 0; } strcpy(tmp_buf, src); tmp_buf[len] = '\n'; if (copy_to_user(ubuf, tmp_buf, len + 1)) { return -EFAULT; } *ppos = len + 1; return len + 1; } static ssize_t mkexec_proc_write(const char __user *ubuf, char *dst, size_t cnt, loff_t *ppos, int maxcnt) { char tmp_buf[MKEXEC_MOD_MAXLEN]; if (*ppos != 0 || cnt > maxcnt) { /* must write at once */ return -EINVAL; } if (copy_from_user(tmp_buf, ubuf, cnt) != 0) { return -EFAULT; } if (tmp_buf[cnt - 1] != 0 && tmp_buf[cnt - 1] != '\n') { return -EINVAL; } tmp_buf[cnt - 1] = 0; memcpy(dst, tmp_buf, cnt); *ppos = cnt; return cnt; } static ssize_t mkexec_read_stats(struct file *file, char __user *ubuf, size_t cnt, loff_t *ppos) { char tmp_buf[2]; tmp_buf[0] = '0' + (char)mkexec_inf.stats; tmp_buf[1] = 0; return mkexec_proc_read(ubuf, tmp_buf, cnt, ppos); } static ssize_t mkexec_write_stats(struct file *file, const char __user *ubuf, size_t cnt, loff_t *ppos) { char tmp_buf[2]; int ret; if ((ret = mkexec_proc_write(ubuf, tmp_buf, cnt, ppos, 2)) < 0) { return ret; } switch (tmp_buf[0]) { case '0': /* mkexec unload */ (void)mkexec_unload(); mkexec_inf.stats = 0; break; case '1': /* mkexec load */ if (mkexec_load() < 0) { /* mini kernel loading */ return -EPERM; break; } mkexec_inf.stats = 1; break; case '2': if (mkexec_inf.stats == 1){ mkexec_inf.stats = 2; /* machine_mexec() is executed out of do_dump(). */ #ifdef MKEXEC_NO_PATCH panic("Compulsory dump(stat of mkexec was set as 2)."); #else do_dump("Compulsory dump(stat of mkexec was set as 2).", NULL); #endif } return -EBUSY; break; default: return -EINVAL; break; } return ret; } static ssize_t mkexec_read_parm(struct file *file, char __user *ubuf, size_t cnt, loff_t *ppos) { return mkexec_proc_read(ubuf, mkexec_inf.parm, cnt, ppos); } static ssize_t mkexec_write_parm(struct file *file, const char __user *ubuf, size_t cnt, loff_t *ppos) { return mkexec_proc_write(ubuf, mkexec_inf.parm, cnt, ppos, MKEXEC_MOD_MAXLEN); } static ssize_t mkexec_read_path(struct file *file, char __user *ubuf, size_t cnt, loff_t *ppos) { return mkexec_proc_read(ubuf, mkexec_inf.path, cnt, ppos); } static ssize_t mkexec_write_path(struct file *file, const char __user *ubuf, size_t cnt, loff_t *ppos) { return mkexec_proc_write(ubuf, mkexec_inf.path, cnt, ppos, MKEXEC_MOD_MAXLEN); } static ssize_t mkexec_read_ddev(struct file *file, char __user *ubuf, size_t cnt, loff_t *ppos) { return mkexec_proc_read(ubuf, mkexec_inf.ddev, cnt, ppos); } static ssize_t mkexec_write_ddev(struct file *file, const char __user *ubuf, size_t cnt, loff_t *ppos) { int ret, err; if ((ret = mkexec_proc_write(ubuf, mkexec_inf.ddev, cnt, ppos, MKEXEC_MOD_MAXDEVLEN)) < 0) { return ret; } if ((err = mkexec_ddev_check(mkexec_inf.ddev)) < 0) { ret = err; mkexec_inf.ddev[0] = 0; } return ret; } static ssize_t mkexec_read_mem(struct file *file, char *ubuf, size_t cnt, loff_t *ppos) { return mkexec_proc_read(ubuf, mkexec_inf.memstr, cnt, ppos); } static ssize_t mkexec_write_mem(struct file *file, const char *ubuf, size_t cnt, loff_t *ppos) { int ret; unsigned long val; char *endp; if ((ret = mkexec_proc_write(ubuf, mkexec_inf.memstr, cnt, ppos, MKEXEC_MOD_MAXDEVLEN)) < 0) { return ret; } val = simple_strtoul(mkexec_inf.memstr, &endp, 0); if (*endp != 0) { goto out; } val = (val + 3) / 4 * MINIK_SEG_SIZE ; /* XXX: sholud not use magic number */ if (val > MAX_MINIK_MEM_SEG * MINIK_SEG_SIZE) { goto out; } mkexec_inf.mem = val; return ret; out: mkexec_inf.memstr[0] = 0; return -EINVAL; } static int mkexec_proc_open(struct inode *ip, struct file *fp) { if (fp->f_mode & FMODE_WRITE && !capable(CAP_SYS_ADMIN)) { return -EPERM; } if (atomic_dec_and_test(&mkexec_inf.sem)) { return 0; } else { atomic_inc(&mkexec_inf.sem); return -EBUSY; } } static int mkexec_proc_close(struct inode *ip, struct file *fp) { atomic_inc(&mkexec_inf.sem); return 0; } static struct file_operations mkexec_proc_ddev_op = { .read = mkexec_read_ddev, .write = mkexec_write_ddev, .open = mkexec_proc_open, .release = mkexec_proc_close }; static struct file_operations mkexec_proc_mem_op = { .read = mkexec_read_mem, .write = mkexec_write_mem, .open = mkexec_proc_open, .release = mkexec_proc_close }; static struct file_operations mkexec_proc_stats_op = { .read = mkexec_read_stats, .write = mkexec_write_stats, .open = mkexec_proc_open, .release = mkexec_proc_close }; static struct file_operations mkexec_proc_path_op = { .read = mkexec_read_path, .write = mkexec_write_path, .open = mkexec_proc_open, .release = mkexec_proc_close }; static struct file_operations mkexec_proc_parm_op = { .read = mkexec_read_parm, .write = mkexec_write_parm, .open = mkexec_proc_open, .release = mkexec_proc_close }; void mkexec_mod_exit(void) { (void)mkexec_unload(); remove_proc_entry(mkexec_proc_path, 0); remove_proc_entry(mkexec_proc_stats, 0); remove_proc_entry(mkexec_proc_parm, 0); remove_proc_entry(mkexec_proc_mem, 0); remove_proc_entry(mkexec_proc_ddev, 0); remove_proc_entry(mkexec_proc_base, 0); } int mkexec_mod_init(void) { struct proc_dir_entry *pe; memset(&mkexec_inf, 0, sizeof(mkexec_inf)); atomic_set(&mkexec_inf.sem, 1); if (proc_mkdir(mkexec_proc_base, 0) == NULL){ printk(KERN_ERR "mkexec: can't create proc entrise.\n"); return -EINVAL; } if ((pe = create_proc_entry(mkexec_proc_stats, 0, 0)) == NULL) { goto out; } pe->proc_fops = &mkexec_proc_stats_op; if ((pe = create_proc_entry(mkexec_proc_parm, 0, 0)) == NULL) { goto out; } pe->proc_fops = &mkexec_proc_parm_op; if ((pe = create_proc_entry(mkexec_proc_path, 0, 0)) == NULL) { goto out; } pe->proc_fops = &mkexec_proc_path_op; if ((pe = create_proc_entry(mkexec_proc_mem, 0, 0)) == NULL) { goto out; } pe->proc_fops = &mkexec_proc_mem_op; if ((pe = create_proc_entry(mkexec_proc_ddev, 0, 0)) == NULL) { goto out; } pe->proc_fops = &mkexec_proc_ddev_op; return 0; out: mkexec_mod_exit(); return -EINVAL; } module_init(mkexec_mod_init); module_exit(mkexec_mod_exit); |
From: Itsuro O. <od...@us...> - 2006-02-14 05:30:36
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12378/3.0/2.6 Added Files: COPYING Makefile README Log Message: register for 3.0: based on 2.1 mkexec-2_0-linux-2_6-2_r --- NEW FILE: README --- README for Mini Kernel Dump (version 2 update 1) ------------------------------------------------ See the following URL for more information about MKDUMP. http://mkdump.sourceforge.net Contents of this package ------------------------ x. README (this file) a. mkexec kernel module mkexec-module-2.1.tar b. mkexec kernel patch b-1) mkexec-patch-2.6.12-2.1 b-2) mkexec-patch-rh-2.4.21-27-2.1 b-3) mkexec-patch-rh-2.4.21-32-2.1 c. mini kernel patch c-1) minik-patch-2.6.12-2.1 c-2) minik-patch-2.6.9-1.2 d. mkdump utilities mkdutils-2.1.tar * support architecture: i386, x86_64 * the following combinations are available = for vanilla kernel +-----------+---------------+--------+ +--------+-------+ +---------+ | mkexec | mkexec | mkexec | | mini | minik | | utility | | kernel | patch | module | | kernel | patch | | | +-----------+---------------+--------+ +--------+-------+ +---------+ | 2.6.12 | b-1 | a | | 2.6.12 | c-1 | | d | | | | | +--------+-------+ | | | | | | | 2.6.9 | c-2 | | | +-----------+---------------+--------+ +--------+-------+ +---------+ = for Red Hat +-----------+---------------+--------+ +--------+-------+ +---------+ | 2.4.21-20 | i386: no need | | | 2.6.9 | c-2 | | | +-----------| x86_64: b-2 | | | | | | | | 2.4.21-27 | | | | | | | | +-----------+---------------| a | | | | | d | | 2.4.21-32 | i386: no need | | | | | | | +-----------| x86_64: b-3 | | | | | | | | 2.4.21-37 | | | | | | | | +-----------+---------------+--------+ +--------+-------+ +---------+ for debian 2.6.8 and vanilla 2.4.27, use the old version of mkdump at this moment. Installation ------------ Mini Kernel Dump consists of three parts: * minik - Mini Kernel Patch to build a special Linux kernel version to dump all the memory to a device. * mkexecpatch - MKEXEC kernel Hook and support functions to be able to load "mkexec-module". This patch must be applied to your standard running Linux kernel to be able to dump its faults. * mkexec-module - MKEXEC kernel module to load Mini Kernel Load this Linux kernel module to "mkexecpatch"-ed Linux kernel to be able to use the dumping functionality. This module will enable you to load 'minik - Mini Kernel' into memory and automatically launch it when needed. Build Mini Kernel ----------------- 1) Prepare the target kernel ex. # cd /usr/src # tar -xjf linux-2.6.12.tar.bz2 # mv linux-2.6.12 linux-minik 2) Apply the patch ex. # cd /usr/src/linux-minik # patch -p4 < minik-patch-2.6.12-2.1 3) Configuration # make menuconfig Turn on CONFIG_DUMP_MINI_KERNEL: * 2.6.9 + minik-patch-2.6.9-1.2 Select "Make dump mini kernel" in the "General setup" * 2.6.12 + minik-patch-2.6.12-2.1 Select "Mini Kernel" in the "Processor type and features" General rules to build a minimized kernel image: - no SMP - no swap - no networking - no filesystems - your required block device driver choose as built-in (Y) 4) Build # make bzImage Note: Do not use "bzImage" for mkexec, use: arch/[i386|x86_64]/boot/compressed/vmlinux.bin Build MKEXEC kernel ------------------- Note: for RHEL3 (i386) this is not necessary. 1) Prepare the target kernel ex. # cd /usr/src # tar -xjf linux-2.6.12.tar.bz2 # mv linux-2.6.12 linux-mkexec 2) Apply the patch ex. # cd /usr/src/linux-mkexec # patch -p4 < mkexec-patch-2.6.12-2.1 3) Configuration # make menuconfig Turn on CONFIG_DUMP_MKEXEC: * 2.6.12 + mkexec-patch-2.6.12-2.1 Select "Mini Kernel - mkexec" in the "Processor type and features" * other no need 4) Build ex. # make bzImage; make modules; make modules_install; make install Build MKEXEC Kernel Module -------------------------- 1) Extract the source ex. # mkdir /usr/src/modules # cd /usr/src/modules # tar -xf mkexec-module-2.1.tar 2) Edit the Makefile # cd /usr/src/modules/mkexec # vi kernel/Makefile Change "ARCH", "KTYPE", "KVER", "TOPDIR" and "THISDIR" for your environment. ex. ARCH = x86_64 # specify "i386" or "x86_64" KTYPE = 24 # specify "24" for kernel 2.4 or "26" for kernel 2.6 TOPDIR = /usr/src/linux-mkexec # specify the top directory of mkexec kernel THISDIR = /usr/src/modules/mkexec/kernel # specify the directory this Makefile exists KVER = 2.6.12-mkexec # specify the kernel suffix (=> /lib/modules/$(KVER)) 3) Make symbolic link # ln -s asm-i386 include/asm # for i386 or # ln -s asm-x86_64 include/asm # for x86_64 4) Make # make Run Mini Kernel Dump -------------------- 1) The MKEXEC kernel boot parameters * 2.6.12 + mkexec-patch-2.6.12-2.1 Add the following parameters to the kernel boot parameters. crashdma=1M crashmain=16M crashdma=nn[KMG] [MKEXEC,KNL] Reserve a chunk of physical memory suitable for a kernel (minik) switched to on panic. This memory will be DMA-able (below 16MB for i386). You should need at most about 1 MB of such memory but it depends a lot on your SCSI controllers. crashmain=nn[KMG] [MKEXEC,KNL] Reserve a chunk of physical memory to hold a kernel (minik) to switch to with mkexec on panic. This memory will be LOW on i386 (16 - 896 MB range). You usually need about 16 MB memory area. * other none 2) Load the MKEXEC module # insmod /usr/src/modules/mkexec/kernel/mkexec.o # for kernel 2.4 or # insmod /usr/src/modules/mkexec/kernel/mkexec.ko # for kernel 2.6 3) Load the Mini kernel Set the dump device: ex. # echo "0x800012" > /proc/mkexec/dumpdev Specify the device number of the dump device. Bits 20..31 are block device major number, bits 0..19 are block device minor. Check the device number of your device by command like: ls -l /dev/sda4 Set the boot parameters of the mini kernel: ex. # echo "console=tty0 console=ttyS0,115200n8r" > /proc/mkexec/parameter * for RHEL3 (i386), the following parameters must be specified "lpj=" and "no-hlt" ex. # echo "lpj=2367488 no-hlt" > /proc/mkexec/parameter * the following parameters are available for the mini kernel mkdump_reboot: specifies action after dump done mkdump_reboot=reboot (default) =halt =poweroff note: working poweroff is hardware dependent dump_delay: specifies wait time before dump start (for waiting completion of device driver initialization) dump_delay=second (default == 5) ex. # echo "mkdump_reboot=halt dump_delay=0" > /proc/mkexec/parameter Set the path name of the mini kernel: ex. # echo "/usr/src/linux-minik/arch/i386/boot/compress/vmlinux.bin" > /proc/mkexec/path Set the amount of memory the mini kernel uses: ex. # echo 16 > /proc/mkexec/mem # reserve 16MB of memory This is necessary only for RHEL3 i386. This must be multiple of 4. Load the mini kernel image: # echo 1 > /proc/mkexec/stats Note: the "mkd_load" utility make above tasks easy. Start the Mini Kernel --------------------- If BUG(), panic() or nmi_watchdog occurs the Mini Dump kernel will be launched. Manual capturing dump: echo 2 >/proc/mkexec/stats Note: for x86_64, /proc/sys/kernel/panic_on_oops should turn on. # echo 1 > /proc/sys/kernel/panic_on_oops *** utilities for the mkdump *** Installation ------------ 1) Extract the source ex. # cd /usr/local/src/ # tar xf mkdutils-2.1.tar 2) Make # cd /usr/local/src/mkdutils # make Contents of this package ------------------------ 1) mkd_load load and setup the mkdump according to the /etc/mkdump/mkdump environment file. 2) mkd_save save the dump from the dump device to a permanent directory according to the /etc/mkdump/mkdump environment file. 3) mkd_chk check the dump device whether the dump was captured or not. this command is used in mkd_save internaly. 4) /etc/mkdump/mkdump see mkdump-config-sample. 5) mkd_conv There are dump format conversion tools. "mini kernel dump" only offers the dump capturing function. You can use any analisys tool by converting the dump format. This directory includes three tools. - mkd2lkcd_i386 mkdump format to lkcd format (for i386) - mkd2lkcd_x86_64 mkdump format to lkcd format (for x86_64) - elf2lkcd_i386 vmcore format to lkcd format (for i386) These codes also intend to explain the mkdump format and to show the format conversion is easy task. Note: we use "crash" command rather than "lcrash" command. Remark ------ these programs are offered as sample programs. there is nowarranty for these programs. -- Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. --- NEW FILE: Makefile --- # # Makefile # # Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. # Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. # # This file is part of Mkdump. # # Mkdump 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 (version 2 of the License). # # Mkdump 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. # # You should have received a copy of the GNU General Public License # along with Mkdump; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # PWD= $(shell pwd) export EXTRA_CFLAGS= -I$(PWD)/include all: make -C ./kernel all clean: make -C ./kernel clean install: make -C ./kernel install uninstall: make -C ./kernel uninstall --- NEW FILE: COPYING --- GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the program's name and a brief idea of what it does.> Copyright (C) <year> <name of author> 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. <signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. |
From: Itsuro O. <od...@us...> - 2006-02-14 05:30:35
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/include/asm-i386 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12378/3.0/2.6/include/asm-i386 Added Files: minik_dump.h mkexec-x86.h mkexec.h mkexec_import.h x86-linux.h Log Message: register for 3.0: based on 2.1 mkexec-2_0-linux-2_6-2_r --- NEW FILE: mkexec_import.h --- /* * include/asm-i386/mkexec_import.h * * $Id: mkexec_import.h,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #define IMPORT_SYMBOL(x) /* dummy */ pte_t *pte_alloc_kernel(struct mm_struct *, pmd_t *, unsigned long); IMPORT_SYMBOL(pte_alloc_kernel); IMPORT_SYMBOL(bust_spinlocks); IMPORT_SYMBOL(e820); IMPORT_SYMBOL(disable_local_APIC); IMPORT_SYMBOL(stop_this_cpu); IMPORT_SYMBOL(disable_IO_APIC); IMPORT_SYMBOL(ioapic_lock); IMPORT_SYMBOL(pgdat_list); IMPORT_SYMBOL(saved_command_line); IMPORT_SYMBOL(crashmem_get); IMPORT_SYMBOL(kallsyms_lookup_name); --- NEW FILE: mkexec.h --- /* * include/asm-i386/mkexec.h * * $Id: mkexec.h,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MKEXEC_H #define MKEXEC_H struct memory_range { unsigned long long start, end; unsigned type; #define RANGE_RAM 0 #define RANGE_RESERVED 1 #define RANGE_ACPI 2 #define RANGE_ACPI_NVS 3 }; extern int pimage_create(struct kimage *image); extern int machine_mkexec_prepare(struct kimage *image); #endif /* MKEXEC_H */ --- NEW FILE: x86-linux.h --- /* * include/asm-i386/x86-linux.h * * $Id: x86-linux.h,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MKEXEC_X86_LINUX_H #define MKEXEC_X86_LINUX_H #define TENATIVE 1 /* Code that is tenatively correct but hasn't yet been officially accepted */ #include <asm/e820.h> #ifndef __ASSEMBLY__ /* FIXME expand on drive_info_)struct... */ struct drive_info_struct { uint8_t dummy[32]; }; struct sys_desc_table { uint16_t length; uint8_t table[318]; }; struct apm_bios_info { uint16_t version; /* 0x40 */ uint16_t cseg; /* 0x42 */ uint32_t offset; /* 0x44 */ uint16_t cseg_16; /* 0x48 */ uint16_t dseg; /* 0x4a */ uint16_t flags; /* 0x4c */ uint16_t cseg_len; /* 0x4e */ uint16_t cseg_16_len; /* 0x50 */ uint16_t dseg_len; /* 0x52 */ uint8_t reserved[44]; /* 0x54 */ }; struct x86_linux_param_header { uint8_t orig_x; /* 0x00 */ uint8_t orig_y; /* 0x01 */ uint16_t ext_mem_k; /* 0x02 -- EXT_MEM_K sits here */ uint16_t orig_video_page; /* 0x04 */ uint8_t orig_video_mode; /* 0x06 */ uint8_t orig_video_cols; /* 0x07 */ uint16_t unused2; /* 0x08 */ uint16_t orig_video_ega_bx; /* 0x0a */ uint16_t unused3; /* 0x0c */ uint8_t orig_video_lines; /* 0x0e */ uint8_t orig_video_isVGA; /* 0x0f */ uint16_t orig_video_points; /* 0x10 */ /* VESA graphic mode -- linear frame buffer */ uint16_t lfb_width; /* 0x12 */ uint16_t lfb_height; /* 0x14 */ uint16_t lfb_depth; /* 0x16 */ uint32_t lfb_base; /* 0x18 */ uint32_t lfb_size; /* 0x1c */ uint16_t cl_magic; /* 0x20 */ #define CL_MAGIC_VALUE 0xA33F uint16_t cl_offset; /* 0x22 */ uint16_t lfb_linelength; /* 0x24 */ uint8_t red_size; /* 0x26 */ uint8_t red_pos; /* 0x27 */ uint8_t green_size; /* 0x28 */ uint8_t green_pos; /* 0x29 */ uint8_t blue_size; /* 0x2a */ uint8_t blue_pos; /* 0x2b */ uint8_t rsvd_size; /* 0x2c */ uint8_t rsvd_pos; /* 0x2d */ uint16_t vesapm_seg; /* 0x2e */ uint16_t vesapm_off; /* 0x30 */ uint16_t pages; /* 0x32 */ uint8_t reserved4[12]; /* 0x34 -- 0x3f reserved for future expansion */ struct apm_bios_info apm_bios_info; /* 0x40 */ struct drive_info_struct drive_info; /* 0x80 */ struct sys_desc_table sys_desc_table; /* 0xa0 */ uint32_t alt_mem_k; /* 0x1e0 */ uint8_t reserved5[4]; /* 0x1e4 */ uint8_t e820_map_nr; /* 0x1e8 */ uint8_t reserved6[8]; /* 0x1e9 */ uint8_t setup_sects; /* 0x1f1 */ uint16_t mount_root_rdonly; /* 0x1f2 */ uint16_t syssize; /* 0x1f4 */ uint16_t swapdev; /* 0x1f6 */ uint16_t ramdisk_flags; /* 0x1f8 */ #define RAMDISK_IMAGE_START_MASK 0x07FF #define RAMDISK_PROMPT_FLAG 0x8000 #define RAMDISK_LOAD_FLAG 0x4000 uint16_t vid_mode; /* 0x1fa */ uint16_t root_dev; /* 0x1fc */ uint8_t reserved9[1]; /* 0x1fe */ uint8_t aux_device_info; /* 0x1ff */ /* 2.00+ */ uint8_t reserved10[2]; /* 0x200 */ uint8_t header_magic[4]; /* 0x202 */ uint16_t protocol_version; /* 0x206 */ uint16_t rmode_switch_ip; /* 0x208 */ uint16_t rmode_switch_cs; /* 0x20a */ uint8_t reserved11[4]; /* 0x20c */ uint8_t loader_type; /* 0x210 */ #define LOADER_TYPE_LOADLIN 1 #define LOADER_TYPE_BOOTSECT_LOADER 2 #define LOADER_TYPE_SYSLINUX 3 #define LOADER_TYPE_ETHERBOOT 4 #define LOADER_TYPE_UNKNOWN 0xFF uint8_t loader_flags; /* 0x211 */ uint8_t reserved12[2]; /* 0x212 */ uint32_t kernel_start; /* 0x214 */ uint32_t initrd_start; /* 0x218 */ uint32_t initrd_size; /* 0x21c */ uint8_t reserved13[4]; /* 0x220 */ /* 2.01+ */ uint16_t heap_end_ptr; /* 0x224 */ uint8_t reserved14[2]; /* 0x226 */ /* 2.02+ */ uint32_t cmd_line_ptr; /* 0x228 */ /* 2.03+ */ uint32_t initrd_addr_max; /* 0x22c */ #if TENATIVE /* 2.04+ */ uint16_t entry32_off; /* 0x230 */ uint16_t internal_cmdline_off; /* 0x232 */ uint32_t low_base; /* 0x234 */ uint32_t low_memsz; /* 0x238 */ uint32_t low_filesz; /* 0x23c */ uint32_t real_base; /* 0x240 */ uint32_t real_memsz; /* 0x244 */ uint32_t real_filesz; /* 0x248 */ uint32_t high_base; /* 0x24C */ uint32_t high_memsz; /* 0x250 */ uint32_t high_filesz; /* 0x254 */ uint8_t reserved15[0x2d0 - 0x258]; /* 0x258 */ #else uint8_t reserved15[0x2d0 - 0x230]; /* 0x230 */ #endif struct e820entry e820_map[E820MAX]; /* 0x2d0 */ /* 0x550 */ #define COMMAND_LINE_SIZE 256 }; struct x86_linux_header { uint8_t reserved1[0x1f1]; /* 0x000 */ uint8_t setup_sects; /* 0x1f1 */ uint16_t root_flags; /* 0x1f2 */ uint16_t syssize; /* 0x1f4 */ uint16_t swapdev; /* 0x1f6 */ uint16_t ramdisk_flags; /* 0x1f6 */ uint16_t vid_mode; /* 0x1fa */ uint16_t root_dev; /* 0x1fc */ uint16_t boot_sector_magic; /* 0x1fe */ /* 2.00+ */ uint8_t reserved3[2]; /* 0x200 */ uint8_t header_magic[4]; /* 0x202 */ uint16_t protocol_version; /* 0x206 */ uint32_t realmode_swtch; /* 0x208 */ uint16_t start_sys; /* 0x20c */ uint16_t kver_addr; /* 0x20e */ uint8_t type_of_loader; /* 0x210 */ uint8_t loadflags; /* 0x211 */ uint16_t setup_move_size; /* 0x212 */ uint32_t code32_start; /* 0x214 */ uint32_t ramdisk_image; /* 0x218 */ uint32_t ramdisk_size; /* 0x21c */ uint8_t reserved4[4]; /* 0x220 */ /* 2.01+ */ uint16_t heap_end_ptr; /* 0x224 */ uint8_t reserved5[2]; /* 0x226 */ /* 2.02+ */ uint32_t cmd_line_ptr; /* 0x228 */ /* 2.03+ */ uint32_t initrd_addr_max; /* 0x22c */ #if TENATIVE /* 2.04+ */ uint16_t entry32_off; /* 0x230 */ uint16_t internal_cmdline_off; /* 0x232 */ uint32_t low_base; /* 0x234 */ uint32_t low_memsz; /* 0x238 */ uint32_t low_filesz; /* 0x23c */ uint32_t real_base; /* 0x240 */ uint32_t real_memsz; /* 0x244 */ uint32_t real_filesz; /* 0x248 */ uint32_t high_base; /* 0x24C */ uint32_t high_memsz; /* 0x250 */ uint32_t high_filesz; /* 0x254 */ uint32_t tail[32*1024 - 0x258]; /* 0x258 */ #else uint8_t tail[32*1024 - 0x230]; /* 0x230 */ #endif } __attribute__ ((packed)); #endif /* ASSEMBLY */ #endif /* MKEXEC_X86_LINUX_H */ --- NEW FILE: mkexec-x86.h --- /* * include/asm-i386/mkexec-x86.h * * $Id: mkexec-x86.h,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MKEXEC_X86_H #define MKEXEC_X86_H extern unsigned char setup32_start[]; extern uint32_t setup32_size; extern struct { uint32_t eax; uint32_t ebx; uint32_t ecx; uint32_t edx; uint32_t esi; uint32_t edi; uint32_t esp; uint32_t ebp; uint32_t eip; } setup32_regs; #endif /* MKEXEC_X86_H */ --- NEW FILE: minik_dump.h --- /* * include/asm-i386/minik_dump.h * * $Id: minik_dump.h,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MINIK_DUMP_H #define MINIK_DUMP_H #include <linux/utsname.h> #define DUMP_NR_CPUS 32 /* 'vmlinux.bin' validity identification. */ #define MINIK_SIGNATURE_OFFSET 4 #define MINIK_SIGNATURE_HEAD "minik001" /* * dump header for i386 */ #define DUMP_PANIC_LEN 128 struct dump_header_i386 { struct dump_version dh_version; /* common info */ u32 dh_dump_cpu; /* cpu id which dump run */ u32 dh_tasks[DUMP_NR_CPUS]; /* current on each cpu */ struct pt_regs dh_regs[DUMP_NR_CPUS]; /* context on each cpu */ char dh_panic_string[DUMP_PANIC_LEN]; struct timespec dh_time; struct new_utsname dh_utsname; }; #ifdef __KERNEL__ #define dump_header dump_header_i386 #endif #endif /* MINIK_DUMP_H */ |
From: Itsuro O. <od...@us...> - 2006-02-14 05:30:35
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/include/asm-x86_64 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12378/3.0/2.6/include/asm-x86_64 Added Files: minik_dump.h mkexec-x86.h mkexec.h mkexec_import.h x86-linux.h Log Message: register for 3.0: based on 2.1 mkexec-2_0-linux-2_6-2_r --- NEW FILE: mkexec_import.h --- /* * include/asm-x86_64/mkexec_import.h * * $Id: mkexec_import.h,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #define IMPORT_SYMBOL(x) /* dummy */ pte_t *pte_alloc_kernel(struct mm_struct *, pmd_t *, unsigned long); IMPORT_SYMBOL(pte_alloc_kernel); IMPORT_SYMBOL(bust_spinlocks); IMPORT_SYMBOL(e820); IMPORT_SYMBOL(disable_local_APIC); IMPORT_SYMBOL(stop_this_cpu); IMPORT_SYMBOL(disable_IO_APIC); IMPORT_SYMBOL(ioapic_lock); IMPORT_SYMBOL(pgdat_list); IMPORT_SYMBOL(saved_command_line); IMPORT_SYMBOL(crashmem_get); IMPORT_SYMBOL(kallsyms_lookup_name); IMPORT_SYMBOL(end_pfn); IMPORT_SYMBOL(mkdump_send_nmi); --- NEW FILE: mkexec.h --- /* * include/asm-x86_64/mkexec.h * * $Id: mkexec.h,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MKEXEC_H #define MKEXEC_H struct memory_range { unsigned long long start, end; unsigned type; #define RANGE_RAM 0 #define RANGE_RESERVED 1 #define RANGE_ACPI 2 #define RANGE_ACPI_NVS 3 }; extern int pimage_create(struct kimage *image); extern int machine_mkexec_prepare(struct kimage *image); #endif /* MKEXEC_H */ --- NEW FILE: x86-linux.h --- /* * include/asm-x86_64/x86-linux.h * * $Id: x86-linux.h,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MKEXEC_X86_LINUX_H #define MKEXEC_X86_LINUX_H #define TENATIVE 0 /* Code that is tenatively correct but hasn't yet been officially accepted */ #include <asm/e820.h> #ifndef ASSEMBLY #define PACKED __attribute__((packed)) /* FIXME expand on drive_info_)struct... */ struct drive_info_struct { uint8_t dummy[32]; }; struct sys_desc_table { uint16_t length; uint8_t table[318]; }; struct apm_bios_info { uint16_t version; /* 0x40 */ uint16_t cseg; /* 0x42 */ uint32_t offset; /* 0x44 */ uint16_t cseg_16; /* 0x48 */ uint16_t dseg; /* 0x4a */ uint16_t flags; /* 0x4c */ uint16_t cseg_len; /* 0x4e */ uint16_t cseg_16_len; /* 0x50 */ uint16_t dseg_len; /* 0x52 */ uint8_t reserved[44]; /* 0x54 */ }; struct x86_linux_param_header { uint8_t orig_x; /* 0x00 */ uint8_t orig_y; /* 0x01 */ uint16_t ext_mem_k; /* 0x02 -- EXT_MEM_K sits here */ uint16_t orig_video_page; /* 0x04 */ uint8_t orig_video_mode; /* 0x06 */ uint8_t orig_video_cols; /* 0x07 */ uint16_t unused2; /* 0x08 */ uint16_t orig_video_ega_bx; /* 0x0a */ uint16_t unused3; /* 0x0c */ uint8_t orig_video_lines; /* 0x0e */ uint8_t orig_video_isVGA; /* 0x0f */ uint16_t orig_video_points; /* 0x10 */ /* VESA graphic mode -- linear frame buffer */ uint16_t lfb_width; /* 0x12 */ uint16_t lfb_height; /* 0x14 */ uint16_t lfb_depth; /* 0x16 */ uint32_t lfb_base; /* 0x18 */ uint32_t lfb_size; /* 0x1c */ uint16_t cl_magic; /* 0x20 */ #define CL_MAGIC_VALUE 0xA33F uint16_t cl_offset; /* 0x22 */ uint16_t lfb_linelength; /* 0x24 */ uint8_t red_size; /* 0x26 */ uint8_t red_pos; /* 0x27 */ uint8_t green_size; /* 0x28 */ uint8_t green_pos; /* 0x29 */ uint8_t blue_size; /* 0x2a */ uint8_t blue_pos; /* 0x2b */ uint8_t rsvd_size; /* 0x2c */ uint8_t rsvd_pos; /* 0x2d */ uint16_t vesapm_seg; /* 0x2e */ uint16_t vesapm_off; /* 0x30 */ uint16_t pages; /* 0x32 */ uint8_t reserved4[12]; /* 0x34 -- 0x3f reserved for future expansion */ struct apm_bios_info apm_bios_info; /* 0x40 */ struct drive_info_struct drive_info; /* 0x80 */ struct sys_desc_table sys_desc_table; /* 0xa0 */ uint32_t alt_mem_k; /* 0x1e0 */ uint8_t reserved5[4]; /* 0x1e4 */ uint8_t e820_map_nr; /* 0x1e8 */ uint8_t reserved6[8]; /* 0x1e9 */ uint8_t setup_sects; /* 0x1f1 */ uint16_t mount_root_rdonly; /* 0x1f2 */ uint16_t syssize; /* 0x1f4 */ uint16_t swapdev; /* 0x1f6 */ uint16_t ramdisk_flags; /* 0x1f8 */ #define RAMDISK_IMAGE_START_MASK 0x07FF #define RAMDISK_PROMPT_FLAG 0x8000 #define RAMDISK_LOAD_FLAG 0x4000 uint16_t vid_mode; /* 0x1fa */ uint16_t root_dev; /* 0x1fc */ uint8_t reserved9[1]; /* 0x1fe */ uint8_t aux_device_info; /* 0x1ff */ /* 2.00+ */ uint8_t reserved10[2]; /* 0x200 */ uint8_t header_magic[4]; /* 0x202 */ uint16_t protocol_version; /* 0x206 */ uint16_t rmode_switch_ip; /* 0x208 */ uint16_t rmode_switch_cs; /* 0x20a */ uint8_t reserved11[4]; /* 0x208 */ uint8_t loader_type; /* 0x210 */ #define LOADER_TYPE_LOADLIN 1 #define LOADER_TYPE_BOOTSECT_LOADER 2 #define LOADER_TYPE_SYSLINUX 3 #define LOADER_TYPE_ETHERBOOT 4 #define LOADER_TYPE_UNKNOWN 0xFF uint8_t loader_flags; /* 0x211 */ uint8_t reserved12[2]; /* 0x212 */ uint32_t kernel_start; /* 0x214 */ uint32_t initrd_start; /* 0x218 */ uint32_t initrd_size; /* 0x21c */ uint8_t reserved13[4]; /* 0x220 */ /* 2.01+ */ uint16_t heap_end_ptr; /* 0x224 */ uint8_t reserved14[2]; /* 0x226 */ /* 2.02+ */ uint32_t cmd_line_ptr; /* 0x228 */ /* 2.03+ */ uint32_t initrd_addr_max; /* 0x22c */ #if TENATIVE /* 2.04+ */ uint16_t entry32_off; /* 0x230 */ uint16_t internal_cmdline_off; /* 0x232 */ uint32_t low_base; /* 0x234 */ uint32_t low_memsz; /* 0x238 */ uint32_t low_filesz; /* 0x23c */ uint32_t real_base; /* 0x240 */ uint32_t real_memsz; /* 0x244 */ uint32_t real_filesz; /* 0x248 */ uint32_t high_base; /* 0x24C */ uint32_t high_memsz; /* 0x250 */ uint32_t high_filesz; /* 0x254 */ uint8_t reserved15[0x2d0 - 0x258]; /* 0x258 */ #else uint8_t reserved15[0x2d0 - 0x230]; /* 0x230 */ #endif struct e820entry e820_map[E820MAX]; /* 0x2d0 */ /* 0x550 */ #define COMMAND_LINE_SIZE 256 }; struct x86_linux_faked_param_header { struct x86_linux_param_header hdr; /* 0x00 */ uint8_t reserved16[688]; /* 0x550 */ uint8_t command_line[COMMAND_LINE_SIZE]; /* 0x800 */ uint8_t reserved17[1792]; /* 0x900 - 0x1000 */ }; struct x86_linux_header { uint8_t reserved1[0x1f1]; /* 0x000 */ uint8_t setup_sects; /* 0x1f1 */ uint16_t root_flags; /* 0x1f2 */ uint16_t syssize; /* 0x1f4 */ uint16_t swapdev; /* 0x1f6 */ uint16_t ramdisk_flags; /* 0x1f6 */ uint16_t vid_mode; /* 0x1fa */ uint16_t root_dev; /* 0x1fc */ uint16_t boot_sector_magic; /* 0x1fe */ /* 2.00+ */ uint8_t reserved3[2]; /* 0x200 */ uint8_t header_magic[4]; /* 0x202 */ uint16_t protocol_version; /* 0x206 */ uint32_t realmode_swtch; /* 0x208 */ uint16_t start_sys; /* 0x20c */ uint16_t kver_addr; /* 0x20e */ uint8_t type_of_loader; /* 0x210 */ uint8_t loadflags; /* 0x211 */ uint16_t setup_move_size; /* 0x212 */ uint32_t code32_start; /* 0x214 */ uint32_t ramdisk_image; /* 0x218 */ uint32_t ramdisk_size; /* 0x21c */ uint8_t reserved4[4]; /* 0x220 */ /* 2.01+ */ uint16_t heap_end_ptr; /* 0x224 */ uint8_t reserved5[2]; /* 0x226 */ /* 2.02+ */ uint32_t cmd_line_ptr; /* 0x228 */ /* 2.03+ */ uint32_t initrd_addr_max; /* 0x22c */ #if TENATIVE /* 2.04+ */ uint16_t entry32_off; /* 0x230 */ uint16_t internal_cmdline_off; /* 0x232 */ uint32_t low_base; /* 0x234 */ uint32_t low_memsz; /* 0x238 */ uint32_t low_filesz; /* 0x23c */ uint32_t real_base; /* 0x240 */ uint32_t real_memsz; /* 0x244 */ uint32_t real_filesz; /* 0x248 */ uint32_t high_base; /* 0x24C */ uint32_t high_memsz; /* 0x250 */ uint32_t high_filesz; /* 0x254 */ uint32_t tail[32*1024 - 0x258]; /* 0x258 */ #else uint8_t tail[32*1024 - 0x230]; /* 0x230 */ #endif } PACKED; #endif /* ASSEMBLY */ #endif /* MKEXEC_X86_LINUX_H */ --- NEW FILE: mkexec-x86.h --- /* * include/asm-i386/mkexec-x86.h * * $Id: mkexec-x86.h,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MKEXEC_X86_H #define MKEXEC_X86_H extern unsigned char setup32_start[]; extern uint32_t setup32_size; extern struct { uint32_t eax; uint32_t ebx; uint32_t ecx; uint32_t edx; uint32_t esi; uint32_t edi; uint32_t esp; uint32_t ebp; uint32_t eip; } setup32_regs; #endif /* MKEXEC_X86_H */ --- NEW FILE: minik_dump.h --- /* * include/asm-x86_64/minik_dump.h * * $Id: minik_dump.h,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MINIK_DUMP_H #define MINIK_DUMP_H #include <linux/utsname.h> #define DUMP_NR_CPUS 32 /* 'vmlinux.bin' validity identification. */ #define MINIK_SIGNATURE_OFFSET 4 #define MINIK_SIGNATURE_HEAD "minik001" /* * dump header for x86_64 */ #define DUMP_PANIC_LEN 128 struct dump_header_x86_64 { struct dump_version dh_version; /* common info */ u32 dh_dump_cpu; /* cpu id which dump run */ u64 dh_tasks[DUMP_NR_CPUS]; /* current on each cpu */ struct pt_regs dh_regs[DUMP_NR_CPUS]; /* context on each cpu */ char dh_panic_string[DUMP_PANIC_LEN]; struct timespec dh_time; struct new_utsname dh_utsname; }; #ifdef __KERNEL__ #define dump_header dump_header_x86_64 #endif #endif /* MINIK_DUMP_H */ |
From: Itsuro O. <od...@us...> - 2006-02-14 05:30:35
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/arch/x86_64/kernel In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12378/3.0/2.6/arch/x86_64/kernel Added Files: machine_mkexec.c minik_dump.c start_new_kernel.S x86_64-setup-32.S Log Message: register for 3.0: based on 2.1 mkexec-2_0-linux-2_6-2_r --- NEW FILE: minik_dump.c --- /* * arch/x86_64/kernel/minik_dump.c * * $Id: minik_dump.c,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <linux/init.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/smp.h> #include <linux/time.h> #include <linux/sched.h> #include <linux/vmalloc.h> #include <linux/mm.h> #include <linux/mmzone.h> #include <linux/delay.h> #include <linux/ptrace.h> #include <linux/utsname.h> #include <linux/mkexec.h> #include <linux/minik_param.h> #include <linux/cpus.h> #include <asm/proto.h> #include <asm/processor.h> #include <asm/e820.h> #include <asm/hardirq.h> #include <asm/nmi.h> #include <asm/apic.h> #include <asm/io_apic.h> #include <asm/minik_dump.h> static struct dump_header *dhp; extern void mkexec_exec(void); static void mem_seg_init(struct mem_seg *mem_segp) { pg_data_t *pgdat; int i; unsigned long avoid_pfn = 0; mem_segp->page_size = PAGE_SIZE; /* XXX: intension: avoid reserved area around 4GB (is there write only area ?) */ /* this code is uncertain for NUMA */ for (i = 0; i < e820.nr_map; i++) { if (e820.map[i].type == E820_RESERVED && e820.map[i].addr > 0xfffff) { avoid_pfn = e820.map[i].addr >> PAGE_SHIFT; break; } } pgdat = pgdat_list; i = 0; if (avoid_pfn && avoid_pfn < pfn_pgdat(pgdat) + size_pgdat(pgdat)) { /* assume start to 0 */ mem_segp->seg_list[i].seg_start_pfn = 0; mem_segp->seg_list[i].seg_size_pfn = avoid_pfn; i++; if (size_pgdat(pgdat) > 0x100000UL) { /* over 4GB */ mem_segp->seg_list[i].seg_start_pfn = 0x100000UL; mem_segp->seg_list[i].seg_size_pfn = size_pgdat(pgdat) - 0x100000UL; i++; } } else { mem_segp->seg_list[i].seg_start_pfn = 0; mem_segp->seg_list[i].seg_size_pfn = size_pgdat(pgdat); i++; } for (pgdat = next_pgdat(pgdat); pgdat && i < MAX_MEM_SEG; pgdat = next_pgdat(pgdat), i++) { mem_segp->seg_list[i].seg_start_pfn = pfn_pgdat(pgdat); mem_segp->seg_list[i].seg_size_pfn = size_pgdat(pgdat); } mem_segp->seg_num = i; } /* * init_dump_header called when dump-mini-kernel load. */ void init_dump_header(struct kimage *image) { unsigned long *addrp; long size; int i; if (image->minik_type == MINIK_V1) { dhp = (struct dump_header *)(__va(image->reserve_mem[0].base_pa) + PAGE_SIZE * 2); } else { dhp = (struct dump_header *)page_address(image->dump_header_pages); } strncpy(dhp->dh_version.dv_magic, DUMP_MAGIC, DUMP_MAGIC_LEN); dhp->dh_version.dv_version = DUMP_VERSION; dhp->dh_version.dv_arch = DUMP_ARCH_X8664; /* dv_unique set later */ /* dh_dump_cpu N/A */ memset(dhp->dh_tasks, 0, sizeof(dhp->dh_tasks)); memset(dhp->dh_regs, 0, sizeof(dhp->dh_regs)); memset(dhp->dh_panic_string, 0, sizeof(dhp->dh_panic_string)); /* dh_time N/A */ dhp->dh_utsname = system_utsname; mem_seg_init((void *)((u8 *)dhp + PAGE_SIZE)); if (image->minik_type == MINIK_V1) { addrp = (unsigned long *)(__va(image->reserve_mem[0].base_pa) + PAGE_SIZE); for (i = 0; i < image->num_minik_mem; i++) { size = image->reserve_mem[i].size_bytes; /* must be multiple 4MB ! */ while (size > 0) { *addrp = image->reserve_mem[i].base_pa + image->reserve_mem[i].size_bytes - size; addrp++; size -= MINIK_SEG_SIZE; } /* ODA: should check addrp range */ } *addrp = 0; } } /* * get current context * (copy from LKCD) */ static inline void get_current_regs(struct pt_regs *regs) { unsigned seg; __asm__ __volatile__("movq %%r15,%0" : "=m"(regs->r15)); __asm__ __volatile__("movq %%r14,%0" : "=m"(regs->r14)); __asm__ __volatile__("movq %%r13,%0" : "=m"(regs->r13)); __asm__ __volatile__("movq %%r12,%0" : "=m"(regs->r12)); __asm__ __volatile__("movq %%r11,%0" : "=m"(regs->r11)); __asm__ __volatile__("movq %%r10,%0" : "=m"(regs->r10)); __asm__ __volatile__("movq %%r9,%0" : "=m"(regs->r9)); __asm__ __volatile__("movq %%r8,%0" : "=m"(regs->r8)); __asm__ __volatile__("movq %%rbx,%0" : "=m"(regs->rbx)); __asm__ __volatile__("movq %%rcx,%0" : "=m"(regs->rcx)); __asm__ __volatile__("movq %%rdx,%0" : "=m"(regs->rdx)); __asm__ __volatile__("movq %%rsi,%0" : "=m"(regs->rsi)); __asm__ __volatile__("movq %%rdi,%0" : "=m"(regs->rdi)); __asm__ __volatile__("movq %%rbp,%0" : "=m"(regs->rbp)); __asm__ __volatile__("movq %%rax,%0" : "=m"(regs->rax)); __asm__ __volatile__("movq %%rsp,%0" : "=m"(regs->rsp)); __asm__ __volatile__("movl %%ss, %0" :"=r"(seg)); regs->ss = (unsigned long)seg; __asm__ __volatile__("movl %%cs, %0" :"=r"(seg)); regs->cs = (unsigned long)seg; __asm__ __volatile__("pushfq; popq %0" :"=m"(regs->eflags)); regs->rip = (unsigned long)current_text_addr(); } #ifdef MKEXEC_NO_PATCH #ifdef CONFIG_X86_IO_APIC extern void disable_IO_APIC(void); extern spinlock_t ioapic_lock; #endif #ifdef CONFIG_X86_LOCAL_APIC extern void disconnect_bsp_APIC(void); #endif static void mkexecreboot(void) { #if defined(CONFIG_X86_LOCAL_APIC) if (cpu_has_apic) { disable_local_APIC(); } #endif #if defined(CONFIG_X86_IO_APIC) spin_lock_init(&ioapic_lock); /* force to lock success */ disable_IO_APIC(); #elif defined(CONFIG_X86_LOCAL_APIC) disconnect_bsp_APIC(); #endif mkexec_exec(); } #else /* MKEXEC_NO_PATCH */ #ifdef CONFIG_X86_IO_APIC static void ioapic_mkexec_restore_once(void) { static int tried[NR_CPUS]; int cpu = get_processor_id(); /* We may crash inside: ioapic_mkexec_restore() */ if (tried[cpu]) return; tried[cpu] = 1; spin_lock_init(&ioapic_lock); /* Force success of locking it inside. */ ioapic_mkexec_restore(); /* errors ignored */ } #endif #ifdef CONFIG_X86_LOCAL_APIC void lapic_mkexec_restore_once(void) { static int tried[NR_CPUS]; int cpu = get_processor_id(); if (!cpu_has_apic) return; /* We may crash inside: lapic_mkexec_restore() */ if (tried[cpu]) return; tried[cpu] = 1; lapic_mkexec_restore(); /* errors ignored */ } #endif static void mkexecreboot(void) { /* Do not: disable_IO_APIC(); * or: disable_local_APIC(); * as we may not imitate the BIOS legacy IRQ0 settings properly. * Later minik may hang-up on: Calibrating delay loop... */ #ifdef CONFIG_X86_IO_APIC ioapic_mkexec_restore_once(); #endif /* CONFIG_X86_IO_APIC */ #ifdef CONFIG_X86_LOCAL_APIC lapic_mkexec_restore_once(); #endif mkexec_exec(); } #endif /* MKEXEC_NO_PATCH */ #ifdef CONFIG_SMP static atomic_t waiting_for_dump_ipi; static int save_done[NR_CPUS]; static int reboot_cpu = 0; void mkdump_send_nmi(void); static void wait_and_mkexecreboot(void) { int i; for (i = 0; i < 1000000000; i++) { if (atomic_read(&waiting_for_dump_ipi) == 0) { break; } } mkexecreboot(); } static int mkdump_nmi_callback(struct pt_regs *regs, int cpu) { if (save_done[cpu]) { return 1; /* anyway now in dump, suppress default nmi handler */ } dhp->dh_tasks[cpu] = (unsigned long)current; dhp->dh_regs[cpu] = *regs; save_done[cpu] = 1; atomic_dec(&waiting_for_dump_ipi); if (cpu == reboot_cpu) { wait_and_mkexecreboot(); } else { stop_this_cpu_safe(NULL); } return 1; } static void stop_other_cpus(void) { int i; int other_cpus = num_online_cpus() - 1; if (other_cpus < 1) { /* Other CPUs are not online and we do not need to stop them. * At least as long as 'cpu_online_map' is valid. */ return; } /* always boot from 0. but if 0 is not online... */ if (!cpu_isset(reboot_cpu, cpu_online_map)) { reboot_cpu = smp_processor_id(); } atomic_set(&waiting_for_dump_ipi, other_cpus); for (i = 0; i < NR_CPUS; i++) { save_done[i] = 0; } set_nmi_callback(mkdump_nmi_callback); wmb(); mkdump_send_nmi(); if (smp_processor_id() == reboot_cpu) { wait_and_mkexecreboot(); } else { stop_this_cpu_safe(NULL); } } #endif /* * start_dump called when dump occur. * save context, stop other cpus and boot mini kernel */ void start_dump(char *panic_str, struct pt_regs *regs, int cpu) { struct pt_regs cur_reg; if (regs == NULL) { get_current_regs(&cur_reg); regs = &cur_reg; } dhp->dh_version.dv_unique = (u32)xtime.tv_sec; dhp->dh_dump_cpu = cpu; #ifdef BACKPORT_24 dhp->dh_time.tv_sec = xtime.tv_sec; dhp->dh_time.tv_nsec = 1000 * xtime.tv_usec; #else dhp->dh_time = xtime; #endif dhp->dh_tasks[cpu] = (unsigned long)current; dhp->dh_regs[cpu] = *regs; strncpy(dhp->dh_panic_string, panic_str, DUMP_PANIC_LEN); #ifdef CONFIG_SMP /* stop_other_cpus() can return. */ stop_other_cpus(); #endif mkexecreboot(); } --- NEW FILE: start_new_kernel.S --- /* * arch/x86_64/kernel/start_new_kernel.S * * $Id: start_new_kernel.S,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. */ /* * Some codes were derived from kexec(relocate_kernel.S) : * * relocate_kernel.S - put the kernel image in place to boot * Copyright (C) 2002-2004 Eric Biederman <ebi...@xm...> * * This source code is licensed under the GNU General Public License, * Version 2. See the file COPYING for more details. */ #include <linux/linkage.h> /* * Must be relocatable PIC code callable as a C function, that once * it starts can not use the previous processes stack. */ .globl start_new_kernel .code64 start_new_kernel: /* %rdi indirection_page * %rsi reboot_code_buffer * %rdx start address * %rcx page_table * %r8 arg5 * %r9 arg6 */ /* zero out flags, and disable interrupts */ pushq $0 popfq /* set a new stack at the bottom of our page... */ lea 4096(%rsi), %rsp /* store the parameters back on the stack */ pushq %rdx /* store the start address */ /* Set cr0 to a known state: * 31 1 == Paging enabled * 18 0 == Alignment check disabled * 16 0 == Write protect disabled * 3 0 == No task switch * 2 0 == Don't do FP software emulation. * 0 1 == Proctected mode enabled */ movq %cr0, %rax andq $~((1<<18)|(1<<16)|(1<<3)|(1<<2)), %rax orl $((1<<31)|(1<<0)), %eax movq %rax, %cr0 /* Set cr4 to a known state: * 10 0 == xmm exceptions disabled * 9 0 == xmm registers instructions disabled * 8 0 == performance monitoring counter disabled * 7 0 == page global disabled * 6 0 == machine check exceptions disabled * 5 1 == physical address extension enabled * 4 0 == page size extensions disabled * 3 0 == Debug extensions disabled * 2 0 == Time stamp disable (disabled) * 1 0 == Protected mode virtual interrupts disabled * 0 0 == VME disabled */ movq $((1<<5)), %rax movq %rax, %cr4 jmp 1f 1: /* Switch to the identity mapped page tables, * and flush the TLB. */ movq %rcx, %cr3 /* set all of the registers to known values */ /* leave %rsp alone */ xorq %rax, %rax xorq %rbx, %rbx xorq %rcx, %rcx xorq %rdx, %rdx xorq %rsi, %rsi // xorq %rdi, %rdi xorq %rbp, %rbp xorq %r8, %r8 xorq %r9, %r9 xorq %r10, %r9 xorq %r11, %r11 xorq %r12, %r12 xorq %r13, %r13 xorq %r14, %r14 xorq %r15, %r15 ret start_new_kernel_end: .globl start_new_kernel_size start_new_kernel_size: .quad start_new_kernel_end - start_new_kernel --- NEW FILE: machine_mkexec.c --- /* * arch/x86_64/kernel/machine_mkexec.c * * $Id: machine_mkexec.c,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. */ /* * Some codes were derived from kexec(machine_kexec.c) * * machine_kexec.c - handle transition of Linux booting another kernel * Copyright (C) 2002-2004 Eric Biederman <ebi...@xm...> * * This source code is licensed under the GNU General Public License, * Version 2. See the file COPYING for more details. */ #include <linux/mm.h> #include <linux/mkexec.h> #include <linux/delay.h> #include <linux/string.h> #include <linux/reboot.h> #include <asm/pda.h> #include <asm/pgtable.h> #include <asm/pgalloc.h> #ifndef BACKPORT_24 #include <asm/tlbflush.h> #endif #include <asm/mmu_context.h> #include <asm/io.h> #include <asm/apic.h> #include <asm/cpufeature.h> #include <asm/hw_irq.h> #include <asm/proto.h> #include <linux/mkexec.h> #include <asm/mkexec-x86_64.h> #define LEVEL0_SIZE (1UL << 12UL) #define LEVEL1_SIZE (1UL << 21UL) #define LEVEL2_SIZE (1UL << 30UL) #define LEVEL3_SIZE (1UL << 39UL) #define LEVEL4_SIZE (1UL << 48UL) #define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) #define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PSE) #define L2_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) #define L3_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) static void init_level2_page( uint64_t *level2p, unsigned long addr) { unsigned long end_addr; addr &= PAGE_MASK; addr &= LEVEL4_SIZE - 1; end_addr = addr + LEVEL2_SIZE; while(addr < end_addr) { #if 0 printk("init_level2_page: addr=0x%lx\n", addr); #endif *(level2p++) = addr | L1_ATTR; addr += LEVEL1_SIZE; } } static int init_level3_page(struct kimage *image, uint64_t *level3p, unsigned long addr, unsigned long first_addr, unsigned long last_addr, unsigned long pa_delta) { unsigned long end_addr; int result; #if 0 printk("init_level3_page: addr=0x%lx, first_addr=0x%lx, last_addr=0x%lx\n", addr, first_addr, last_addr); #endif result = 0; end_addr = addr + LEVEL3_SIZE; for (;addr < end_addr && addr < last_addr; level3p++, addr += LEVEL2_SIZE) { struct page *page; uint64_t *level2p; if (addr + LEVEL2_SIZE <= first_addr) continue; if (image->num_control_page >= ARRAY_SIZE(image->control_page)) { result = -ENOBUFS; goto out; } page = alloc_pages(GFP_KERNEL | GFP_DMA, 0); if (!page) { result = -ENOMEM; goto out; } // page->mapping = NULL; // page->private = 0; // SetPageReserved(page); image->control_page[image->num_control_page++] = page; level2p = (uint64_t *)page_address(page); init_level2_page(level2p, addr + pa_delta); *level3p = __pa(level2p) | L2_ATTR; } out: return result; } static int init_level4_page(struct kimage *image, uint64_t *level4p, unsigned long first_addr, unsigned long last_addr, unsigned long pa_delta) { int result; unsigned long addr; result = 0; /* x86_64 handles/pages only 48 bits! */ first_addr &= LEVEL4_SIZE - 1; last_addr &= LEVEL4_SIZE - 1; for (addr = 0; addr < last_addr; level4p++, addr += LEVEL3_SIZE) { struct page *page; uint64_t *level3p; #if 0 printk("init_level4_page: addr=0x%lx, first_addr=0x%lx, last_addr=0x%lx\n", addr, first_addr, last_addr); #endif if (addr + LEVEL3_SIZE <= first_addr) continue; if (image->num_control_page >= ARRAY_SIZE(image->control_page)) { result = -ENOBUFS; goto out; } page = alloc_pages(GFP_KERNEL | GFP_DMA, 0); if (!page) { result = -ENOMEM; goto out; } // page->mapping = NULL; // page->private = 0; // SetPageReserved(page); image->control_page[image->num_control_page++] = page; level3p = (uint64_t *)page_address(page); memset(level3p, 0, PAGE_SIZE); result = init_level3_page(image, level3p, addr, first_addr, last_addr, pa_delta); if (result) { goto out; } *level4p = __pa(level3p) | L3_ATTR; } out: return result; } static int init_pgtable(struct kimage *image, unsigned long start_pgtable) { uint64_t *level4p; int result; level4p = (uint64_t *)__va(start_pgtable); memset(level4p, 0, PAGE_SIZE); result = init_level4_page(image, level4p, 0, end_pfn << PAGE_SHIFT, 0); if (result) return result; /* Be aware '__PAGE_OFFSET' mapping is missing here - not required. */ /* In fact '__START_KERNEL_map' is also not needed, sometimes somehow CPU cached. */ return init_level4_page(image, level4p, __START_KERNEL_map, LEVEL4_SIZE - 1, /* __pa() adjusts by: physical_start_offset */ -__START_KERNEL_map + __pa(__START_KERNEL_map)); } static void set_idt(void *newidt_va, __u16 limit) { unsigned char curidt[10]; /* x86-64 supports unaliged loads & stores */ (*(__u16 *)(curidt)) = limit; (*(__u64 *)(curidt +2)) = __pa(newidt_va); __asm__ __volatile__ ( "lidt %0\n" : "=m" (curidt) ); }; static void set_gdt(void *newgdt_va, __u16 limit) { unsigned char curgdt[10]; /* x86-64 supports unaligned loads & stores */ (*(__u16 *)(curgdt)) = limit; (*(__u64 *)(curgdt +2)) = __pa(newgdt_va); __asm__ __volatile__ ( "lgdt %0\n" : "=m" (curgdt) ); }; static void load_segments(void) { __asm__ __volatile__ ( "\tmovl $"STR(__KERNEL_DS)",%eax\n" "\tmovl %eax,%ds\n" "\tmovl %eax,%es\n" "\tmovl %eax,%ss\n" "\tmovl %eax,%fs\n" "\tmovl %eax,%gs\n" ); #undef STR #undef __STR } int machine_mkexec_prepare(struct kimage *image) { unsigned long start_pgtable, control_code_buffer; int result; struct page *page; if (image->num_control_page >= ARRAY_SIZE(image->control_page)) return -ENOBUFS; /* Calculate the offsets */ page = alloc_pages(GFP_KERNEL | GFP_DMA, 0); // page->mapping = NULL; // page->private = 0; // SetPageReserved(page); image->control_page[image->num_control_page++] = page; image->control_code_page = page; start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT; control_code_buffer = image->new_kernel_paddr; /* Setup the identity mapped 64bit page table */ result = init_pgtable(image, start_pgtable); if (result) { int num; for(num = image->num_control_page-1; num >= 0; num--){ __free_pages(image->control_page[num], 0); } image->num_control_page = 0; return result; } /* Place the code in the reboot code buffer */ // memcpy(__va(control_code_buffer), start_new_kernel, start_new_kernel_size); // image->reboot_code_addr = control_code_buffer; return 0; } void machine_kexec_cleanup(struct kimage *image) { return; } typedef asmlinkage void (*start_new_kernel_t)( unsigned long indirection_page, unsigned long reboot_code_buffer, unsigned long start_address, unsigned int has_pae); const extern unsigned char start_new_kernel[]; extern void start_new_kernel_end(void); const extern unsigned int start_new_kernel_size; /* * Do not allocate memory (or fail in any way) in machine_kexec(). * We are past the point of no return, committed to rebooting now. */ void machine_mkexec(struct kimage *image) { unsigned long control_code_buffer; unsigned long start_pgtable; start_new_kernel_t rnk; /* Interrupts aren't acceptable while we reboot */ local_irq_disable(); /* Calculate the offsets */ start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT; control_code_buffer = image->reboot_code_addr; /* Set the low half of the page table to my identity mapped * page table for kexec. Leave the high half pointing at the * kernel pages. Don't bother to flush the global pages * as that will happen when I fully switch to my identity mapped * page table anyway. */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12) load_cr3(__va(start_pgtable)); #else memcpy((void *)read_pda(level4_pgt), __va(start_pgtable), PAGE_SIZE/2); #endif __flush_tlb(); /* The segment registers are funny things, they are * automatically loaded from a table, in memory wherever you * set them to a specific selector, but this table is never * accessed again unless you set the segment to a different selector. * * The more common model are caches where the behide * the scenes work is done, but is also dropped at arbitrary * times. * * I take advantage of this here by force loading the * segments, before I zap the gdt with an invalid value. */ load_segments(); /* The gdt & idt are now invalid. * If you want to load them you must set up your own idt & gdt. */ set_gdt(phys_to_virt(0),0); set_idt(phys_to_virt(0),0); /* now call it */ rnk = (start_new_kernel_t)image->reboot_code_addr; (*rnk)(image->new_kernel_paddr, image->reboot_code_addr, image->start+image->new_kernel_paddr, start_pgtable); } --- NEW FILE: x86_64-setup-32.S --- /* * arch/x86_64/kernel/x86_64-setup-32.S * * mkexec: Linux boots Linux(Mini kernel) * * $Id: x86_64-setup-32.S,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. */ /* * Some codes were derived from kexec : * * kexec: Linux boots Linux * * Copyright (C) 2003,2004 Eric Biederman (ebi...@xm...) * * 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 (version 2 of the License). * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ .data .equ MSR_K6_EFER, 0xC0000080 .equ EFER_LME, 0x00000100 .equ X86_CR4_PAE, 0x00000020 .equ CR0_PG, 0x80000000 .globl setup32_start, setup32_end, setup32_size .globl setup32_regs setup32_start: _reloc = . .code64 /* Compute where I am running at */ leaq setup32_start(%rip), %rbx /* Relocate the code */ addq %rbx, lreloc1(%rip) addl %ebx, reloc1(%rip) addl %ebx, reloc2(%rip) addl %ebx, reloc3(%rip) /* Setup a gdt that should be preserved */ /* This also acts as a serializing instruction ensuring * my self modifying code works. */ lgdt gdt(%rip) /* Switch to 32bit compatiblity mode */ ljmp *lm_exit_addr(%rip) lm_exit: .code32 /* addl %edi, ebx - _reloc(%ebx)*/ addl %edi, eip - _reloc(%ebx) addl %edi, esp - _reloc(%ebx) addl %edi, esi - _reloc(%ebx) /* Disable paging */ movl %cr0, %eax andl $~CR0_PG, %eax movl %eax, %cr0 /* Disable long mode */ movl $MSR_K6_EFER, %ecx rdmsr andl $~EFER_LME, %eax wrmsr /* Disable PAE */ xorl %eax, %eax movl %eax, %cr4 /* load the data segments */ movl $0x18, %eax /* data segment */ movl %eax, %ds movl %eax, %es movl %eax, %ss movl %eax, %fs movl %eax, %gs /* Load the registers */ movl eax - _reloc(%ebx), %eax movl ecx - _reloc(%ebx), %ecx movl edx - _reloc(%ebx), %edx movl esi - _reloc(%ebx), %esi movl edi - _reloc(%ebx), %edi movl esp - _reloc(%ebx), %esp movl ebp - _reloc(%ebx), %ebp /* * 5: * jmp 5b */ .byte 0x8b, 0x1d # movl ebx, %ebx reloc1: .long ebx - _reloc nop nop /* * 5: * jmp 5b */ .byte 0xff, 0x25 # jmpl *(eip) reloc2: .long eip - _reloc nop nop .balign 4 setup32_regs: eax: .long 0x00000000 ebx: .long 0x00000000 ecx: .long 0x00000000 edx: .long 0x00000000 esi: .long 0x00000000 edi: .long 0x00000000 esp: .long 0x00000000 ebp: .long 0x00000000 eip: .long 0x00000000 .balign 16 gdt: /* 0x00 unusable segment * 0x08 unused * so use them as the gdt ptr */ .word gdt_end - gdt - 1 lreloc1: .quad gdt - _reloc .word 0, 0, 0 /* Documented linux kernel segments */ /* 0x10 4GB flat code segment */ .word 0xFFFF, 0x0000, 0x9A00, 0x00CF /* 0x18 4GB flat data segment */ .word 0xFFFF, 0x0000, 0x9200, 0x00CF /* 0x20 dummy */ .word 0x0000, 0x0000, 0x0000, 0x000 /* 0x28 dummy */ .word 0x0000, 0x0000, 0x0000, 0x000 /* 0x30 dummy */ .word 0x0000, 0x0000, 0x0000, 0x000 /* 0x38 dummy */ .word 0x0000, 0x0000, 0x0000, 0x000 /* 0x40 dummy */ .word 0x0000, 0x0000, 0x0000, 0x000 /* 0x48 dummy */ .word 0x0000, 0x0000, 0x0000, 0x000 /* 0x50 dummy */ .word 0x0000, 0x0000, 0x0000, 0x000 /* 0x58 dummy */ .word 0x0000, 0x0000, 0x0000, 0x000 /* Segments used by the 2.5.x kernel */ /* 0x60 4GB flat code segment */ .word 0xFFFF, 0x0000, 0x9A00, 0x00CF /* 0x68 4GB flat data segment */ .word 0xFFFF, 0x0000, 0x9200, 0x00CF gdt_end: lm_exit_addr: reloc3: .long lm_exit - _reloc .long 0x10 reloc4: .quad 0 setup32_end: setup32_size: .long setup32_end - setup32_start |
From: Itsuro O. <od...@us...> - 2006-02-14 05:30:34
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/include/linux In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12378/3.0/2.6/include/linux Added Files: mkexec.h cpus.h minik_param.h mkexec_ex.h Log Message: register for 3.0: based on 2.1 mkexec-2_0-linux-2_6-2_r --- NEW FILE: cpus.h --- /* * include/linux/cpus.h * * $Id: cpus.h,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * Written by Fernando Luis Vazquez Cao * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _CPUS_H #define _CPUS_H #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) #define get_processor_id() (0) #define convert_apicid_to_cpu(apic_id) (0xff) void stop_this_cpu(void *); #define stop_this_cpu_safe(a) stop_this_cpu(a) #else /* kernel 2.6 */ #ifndef CONFIG_SMP #define get_processor_id() (0) #define convert_apicid_to_cpu(apic_id) (0xff) #else /* !CONFIG_SMP */ #include <linux/smp.h> #if defined(CONFIG_IA64) || defined(CONFIG_X86_64) || defined(CONFIG_X86) #ifdef CONFIG_IA64 #define arch_cpu_to_apicid ia64_cpu_to_sapicid #define ARCH_BAD_APICID (0xffff) #error "FIXME: convert_apicid_to_cpu() u8 type broken for ia64" #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9) #define arch_cpu_to_apicid x86_cpu_to_apicid #define ARCH_BAD_APICID (0xff) #endif #if defined(CONFIG_IA64) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9)) static inline u8 convert_apicid_to_cpu(u16 apic_id) { int i; for (i = 0; i < NR_CPUS; i++) { if (arch_cpu_to_apicid[i] == apic_id) return i; } return -1; } /* Replacement for smp_processor_id() as on i386 * its 'current_thread_info()->cpu' gets corrupted during a stack overflow. */ static inline u8 get_processor_id(void) { u16 apic_id; /* apic_id = hard_smp_processor_id(); */ apic_id = GET_APIC_ID(apic_read(APIC_ID)); if (apic_id == ARCH_BAD_APICID) return -1; return convert_apicid_to_cpu(apic_id); } #else /* before 2.6.9 */ #define get_processor_id() smp_processor_id() #define convert_apicid_to_cpu(apic_id) (0xff) #endif static inline void stop_this_cpu_safe (void *dummy) { int cpuid = get_processor_id(); cpu_clear(cpuid, cpu_online_map); local_irq_disable(); #if defined(CONFIG_X86_LOCAL_APIC) lapic_mkexec_restore_once(); #endif #if defined(CONFIG_X86) && !defined(CONFIG_X86_64) if (cpu_data[cpuid].hlt_works_ok) #endif for(;;) __asm__("hlt"); for (;;); } #else /* defined(CONFIG_IA64)||defined(CONFIG_X86_64)||defined(CONFIG_X86) */ #define get_processor_id() smp_processor_id() #define convert_apicid_to_cpu(apic_id) (0xff) #endif /* defined(CONFIG_IA64)||defined(CONFIG_X86_64)||defined(CONFIG_X86) */ #endif /* !CONFIG_SMP */ #endif /* kernel 2.6 */ #endif /* _CPUS_H */ --- NEW FILE: mkexec_ex.h --- /* * include/linux/mkexec_ex.h * * $Id: mkexec_ex.h,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef LINUX_MKEXEC_EX_H #define LINUX_MKEXEC_EX_H #ifndef CONFIG_DUMP_MKEXEC #define MKEXEC_NO_PATCH /* indicates the kernel not apply mkexec-patch */ struct crashmem { unsigned long base_pa; unsigned long size_bytes; }; extern struct crashmem *crashmem_get(int); #endif /* for 2.4 kernel */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) #define BACKPORT_24 #define __user #define global_flush_tlb() flush_tlb_all() #ifdef CONFIG_SMP #if NR_CPUS > 32 #error "to many cpus" #endif #include <linux/bitops.h> #define cpu_isset(cpu, map) test_bit(cpu, &(map)) #define num_online_cpus() hweight32(cpu_online_map) #endif static inline dev_t convert_old_dev(int dev) { dev_t old_dev; old_dev = MKDEV(dev >> 20, dev & 0xfffff); return old_dev; } /* for pgdat_list member imcompatibility: 2.4 version */ #define next_pgdat(p) (p->node_next) #define size_pgdat(p) (p->node_size) #define pfn_pgdat(p) (p->node_start_paddr >> PAGE_SHIFT) #else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */ /* for pgdat_list member imcompatibility: 2.6 version */ #define next_pgdat(p) (p->pgdat_next) #define size_pgdat(p) (p->node_spanned_pages) #define pfn_pgdat(p) (p->node_start_pfn) #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */ #endif /* LINUX_MKEXEC_EX_H */ --- NEW FILE: minik_param.h --- /* * include/linux/minik_param.h * * $Id: minik_param.h,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * dump_header must be defined for every arch each. * the first member must be dump_version. */ #define DUMP_MAGIC_LEN 10 struct dump_version { char dv_magic[DUMP_MAGIC_LEN]; u8 dv_version; u8 dv_arch; u32 dv_unique; }; #define DUMP_MAGIC "MINIK_DUMP" #define DUMP_VERSION 1 #define DUMP_ARCH_I386 1 #define DUMP_ARCH_X8664 2 #define DUMP_ARCH_IA64 3 #ifdef __KERNEL__ extern void init_dump_header(struct kimage *image); extern void lapic_mkexec_restore_once(void); extern void start_dump(char *, struct pt_regs *, int); extern void do_minik_dump(char *panic_str, struct pt_regs *regs); #endif --- NEW FILE: mkexec.h --- /* * include/linux/mkexec.h * * $Id: mkexec.h,v 1.1 2006/02/14 05:30:26 odaodab Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump 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 (version 2 of the License). * * Mkdump 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. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef LINUX_MKEXEC_H #define LINUX_MKEXEC_H #include <linux/types.h> #include <linux/version.h> #define MKEXEC_SEGMENT_MAX 3 struct mkexec_segment { void *buf; size_t bufsz; void *mem; size_t memsz; }; #define MAX_MINIK_MEM_SEG 32 #define MINIK_SEG_SIZE 0x400000 /* 4MB */ #define MINIK_SEG_SHIFT 22 #define MINIK_SEG_MASK 0x3fffff struct mkexec_reserve_mem { unsigned long base_pa; unsigned long size_bytes; struct page *pages; int order; }; #define MINIK_V1 0 #define MINIK_V2 1 #define MKEXEC_CONTROL_PAGES_MAX 32 struct kimage { unsigned long new_kernel_paddr; unsigned long start; unsigned long reboot_code_addr; unsigned long nr_segments; /* ODA: remove --> enum */ struct mkexec_segment segment[MKEXEC_SEGMENT_MAX]; int minik_type; struct mkexec_reserve_mem reserve_mem_dma; struct mkexec_reserve_mem reserve_mem[MAX_MINIK_MEM_SEG]; int num_minik_mem; int num_control_page; struct page *control_code_page; struct page *control_page[MKEXEC_CONTROL_PAGES_MAX]; struct page *dump_header_pages; }; /* mkexec interface functions */ extern void machine_mkexec(struct kimage *image); extern struct kimage *mkexec_image; const extern unsigned char start_new_kernel[]; extern void start_new_kernel_end(void); const extern unsigned int start_new_kernel_size; /* * /proc/mkexec */ #define MKEXEC_MOD_MAXLEN 256 #define MKEXEC_MOD_MAXDEVLEN 16 typedef struct { int stats; char path[MKEXEC_MOD_MAXLEN]; char parm[MKEXEC_MOD_MAXLEN]; char ddev[MKEXEC_MOD_MAXDEVLEN]; char memstr[MKEXEC_MOD_MAXDEVLEN]; int mem; atomic_t sem; int writ_cnt; } mkexec_mod_t; extern mkexec_mod_t mkexec_inf; #define MAX_MEM_SEG 62 /* struct mem_seg <= 4KB (1 page) */ struct mem_seg_list { u64 seg_start_pfn; u64 seg_size_pfn; }; struct mem_seg { u32 page_size; u32 seg_num; struct mem_seg_list seg_list[MAX_MEM_SEG]; }; #include <linux/mkexec_ex.h> #ifndef MKEXEC_NO_PATCH #include <linux/mkexec_dump.h> #include <asm/mkexec_export.h> #endif #endif /* LINUX_MKEXEC_H */ |
From: Itsuro O. <od...@us...> - 2006-02-14 05:25:11
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/kernel In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11086/3.0/2.6/kernel Log Message: Directory /cvsroot/mkdump/mkexec/3.0/2.6/kernel added to the repository |
From: Itsuro O. <od...@us...> - 2006-02-14 05:25:05
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/include/linux In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10982/3.0/2.6/include/linux Log Message: Directory /cvsroot/mkdump/mkexec/3.0/2.6/include/linux added to the repository |
From: Itsuro O. <od...@us...> - 2006-02-14 05:24:58
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/include/asm-x86_64 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10968/3.0/2.6/include/asm-x86_64 Log Message: Directory /cvsroot/mkdump/mkexec/3.0/2.6/include/asm-x86_64 added to the repository |