/* Reads a page from the oldmem device from given offset. */ static ssize_t read_from_oldmem(char *buf, size_t count, u64 *ppos, int userbuf) { unsigned long pfn, offset; size_t nr_bytes; ssize_t read = 0, tmp; if (!count) return 0; offset = (unsigned long)(*ppos % PAGE_SIZE); pfn = (unsigned long)(*ppos / PAGE_SIZE); if (pfn > saved_max_pfn) return -EINVAL; do { if (count > (PAGE_SIZE - offset)) nr_bytes = PAGE_SIZE - offset; else nr_bytes = count; tmp = copy_oldmem_page(pfn, buf, nr_bytes, offset, userbuf); if (tmp < 0) return tmp; *ppos += nr_bytes; count -= nr_bytes; buf += nr_bytes; read += nr_bytes; ++pfn; offset = 0; } while (count); return read; }
/* Reads a page from the oldmem device from given offset. */ static ssize_t read_from_oldmem(char *buf, size_t count, u64 *ppos, int userbuf) { unsigned long pfn, offset; size_t nr_bytes; ssize_t read = 0, tmp; if (!count) return 0; offset = (unsigned long)(*ppos % PAGE_SIZE); pfn = (unsigned long)(*ppos / PAGE_SIZE); do { if (count > (PAGE_SIZE - offset)) nr_bytes = PAGE_SIZE - offset; else nr_bytes = count; /* If pfn is not ram, return zeros for sparse dump files */ if (pfn_is_ram(pfn) == 0) { if (userbuf) { if (clear_user((char __force_user *)buf, nr_bytes)) return -EFAULT; } else memset(buf, 0, nr_bytes); } else { tmp = copy_oldmem_page(pfn, buf, nr_bytes, offset, userbuf); if (tmp < 0) return tmp; } *ppos += nr_bytes; count -= nr_bytes; buf += nr_bytes; read += nr_bytes; ++pfn; offset = 0; } while (count); return read; }
static void __init smp_detect_cpus(void) { unsigned int cpu, c_cpus, s_cpus; struct sclp_cpu_info *info; u16 boot_cpu_addr, cpu_addr; c_cpus = 1; s_cpus = 0; boot_cpu_addr = __cpu_logical_map[0]; info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) panic("smp_detect_cpus failed to allocate memory\n"); #ifdef CONFIG_CRASH_DUMP if (OLDMEM_BASE && !is_kdump_kernel()) { struct save_area *save_area; save_area = kmalloc(sizeof(*save_area), GFP_KERNEL); if (!save_area) panic("could not allocate memory for save area\n"); copy_oldmem_page(1, (void *) save_area, sizeof(*save_area), 0x200, 0); zfcpdump_save_areas[0] = save_area; } #endif /* Use sigp detection algorithm if sclp doesn't work. */ if (sclp_get_cpu_info(info)) { smp_use_sigp_detection = 1; for (cpu = 0; cpu <= MAX_CPU_ADDRESS; cpu++) { if (cpu == boot_cpu_addr) continue; if (!raw_cpu_stopped(cpu)) continue; smp_get_save_area(c_cpus, cpu); c_cpus++; } goto out; } if (info->has_cpu_type) { for (cpu = 0; cpu < info->combined; cpu++) { if (info->cpu[cpu].address == boot_cpu_addr) { smp_cpu_type = info->cpu[cpu].type; break; } } } for (cpu = 0; cpu < info->combined; cpu++) { if (info->has_cpu_type && info->cpu[cpu].type != smp_cpu_type) continue; cpu_addr = info->cpu[cpu].address; if (cpu_addr == boot_cpu_addr) continue; if (!raw_cpu_stopped(cpu_addr)) { s_cpus++; continue; } smp_get_save_area(c_cpus, cpu_addr); c_cpus++; } out: kfree(info); pr_info("%d configured CPUs, %d standby CPUs\n", c_cpus, s_cpus); get_online_cpus(); __smp_rescan_cpus(); put_online_cpus(); }