diff options
author | Stewart Smith <stewart@linux.ibm.com> | 2018-06-28 12:54:58 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.ibm.com> | 2018-07-16 23:48:30 -0500 |
commit | 21f540e8e51e79bbd56f831764ce5e1e8627051a (patch) | |
tree | 80a6c18d8afd304e1b304c03a9e0161361c35f24 | |
parent | 06808a037d44231ba36e814ff1dbf66bc8b707da (diff) | |
download | skiboot-21f540e8e51e79bbd56f831764ce5e1e8627051a.zip skiboot-21f540e8e51e79bbd56f831764ce5e1e8627051a.tar.gz skiboot-21f540e8e51e79bbd56f831764ce5e1e8627051a.tar.bz2 |
Scan PCI and clear memory simultaneously
For many systems, scanning PCI takes about as much time as
zeroing all of RAM, so we may as well do them at the same time
and cut a few seconds off the total fast reboot time.
Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
-rw-r--r-- | core/fast-reboot.c | 5 | ||||
-rw-r--r-- | core/mem_region.c | 51 | ||||
-rw-r--r-- | include/mem_region.h | 3 |
3 files changed, 40 insertions, 19 deletions
diff --git a/core/fast-reboot.c b/core/fast-reboot.c index 5681975..56d6b3b 100644 --- a/core/fast-reboot.c +++ b/core/fast-reboot.c @@ -374,6 +374,9 @@ void __noreturn fast_reboot_entry(void) /* Start preloading kernel and ramdisk */ start_preload_kernel(); + /* Start clearing memory */ + start_mem_region_clear_unused(); + /* Poke the consoles (see comments in the code there) */ fsp_console_reset(); @@ -399,7 +402,7 @@ void __noreturn fast_reboot_entry(void) ipmi_set_fw_progress_sensor(IPMI_FW_PCI_INIT); - mem_region_clear_unused(); + wait_mem_region_clear_unused(); /* Load and boot payload */ load_and_boot_kernel(true); diff --git a/core/mem_region.c b/core/mem_region.c index 728c421..e9f2892 100644 --- a/core/mem_region.c +++ b/core/mem_region.c @@ -1224,31 +1224,38 @@ static void mem_region_clear_job(void *data) #define MEM_REGION_CLEAR_JOB_SIZE (16ULL*(1<<30)) -void mem_region_clear_unused(void) +static struct cpu_job **mem_clear_jobs; +static struct mem_region_clear_job_args *mem_clear_job_args; +static int mem_clear_njobs = 0; + +void start_mem_region_clear_unused(void) { - int njobs = 0; - struct cpu_job **jobs; struct mem_region *r; - struct mem_region_clear_job_args *job_args; uint64_t s,l; uint64_t total = 0; uint32_t chip_id; char *path; int i; + struct cpu_job **jobs; + struct mem_region_clear_job_args *job_args; lock(&mem_region_lock); assert(mem_regions_finalised); + mem_clear_njobs = 0; + list_for_each(®ions, r, list) { if (!(r->type == REGION_OS)) continue; - njobs++; + mem_clear_njobs++; /* One job per 16GB */ - njobs += r->len / MEM_REGION_CLEAR_JOB_SIZE; + mem_clear_njobs += r->len / MEM_REGION_CLEAR_JOB_SIZE; } - jobs = malloc(njobs * sizeof(struct cpu_job*)); - job_args = malloc(njobs * sizeof(struct mem_region_clear_job_args)); + jobs = malloc(mem_clear_njobs * sizeof(struct cpu_job*)); + job_args = malloc(mem_clear_njobs * sizeof(struct mem_region_clear_job_args)); + mem_clear_jobs = jobs; + mem_clear_job_args = job_args; prlog(PR_NOTICE, "Clearing unused memory:\n"); i = 0; @@ -1278,7 +1285,6 @@ void mem_region_clear_unused(void) (job_args[i].e - job_args[i].s), chip_id); free(path); - printf("job: %s\n", job_args[i].job_name); jobs[i] = cpu_queue_job_on_node(chip_id, job_args[i].job_name, mem_region_clear_job, @@ -1306,25 +1312,36 @@ void mem_region_clear_unused(void) (job_args[i].e - job_args[i].s), chip_id); free(path); - printf("job: %s\n", job_args[i].job_name); jobs[i] = cpu_queue_job_on_node(chip_id, job_args[i].job_name, mem_region_clear_job, &job_args[i]); i++; } + unlock(&mem_region_lock); cpu_process_local_jobs(); +} + +void wait_mem_region_clear_unused(void) +{ + uint64_t l; + uint64_t total = 0; + int i; + + for(i=0; i < mem_clear_njobs; i++) { + total += (mem_clear_job_args[i].e - mem_clear_job_args[i].s); + } + l = 0; - for(i=0; i < njobs; i++) { - cpu_wait_job(jobs[i], true); - l += (job_args[i].e - job_args[i].s); + for(i=0; i < mem_clear_njobs; i++) { + cpu_wait_job(mem_clear_jobs[i], true); + l += (mem_clear_job_args[i].e - mem_clear_job_args[i].s); printf("Clearing memory... %"PRIu64"/%"PRIu64"GB done\n", l>>30, total>>30); - free(job_args[i].job_name); + free(mem_clear_job_args[i].job_name); } - unlock(&mem_region_lock); - free(jobs); - free(job_args); + free(mem_clear_jobs); + free(mem_clear_job_args); } static void mem_region_add_dt_reserved_node(struct dt_node *parent, diff --git a/include/mem_region.h b/include/mem_region.h index 9e288da..018dfa0 100644 --- a/include/mem_region.h +++ b/include/mem_region.h @@ -65,7 +65,8 @@ size_t mem_allocated_size(const void *ptr); bool mem_check(const struct mem_region *region); bool mem_check_all(void); void mem_region_release_unused(void); -void mem_region_clear_unused(void); +void start_mem_region_clear_unused(void); +void wait_mem_region_clear_unused(void); int64_t mem_dump_free(void); void mem_dump_allocs(void); |