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; |