aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStewart Smith <stewart@linux.ibm.com>2018-06-28 12:54:58 +1000
committerStewart Smith <stewart@linux.ibm.com>2018-07-16 23:48:30 -0500
commit21f540e8e51e79bbd56f831764ce5e1e8627051a (patch)
tree80a6c18d8afd304e1b304c03a9e0161361c35f24
parent06808a037d44231ba36e814ff1dbf66bc8b707da (diff)
downloadskiboot-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.c5
-rw-r--r--core/mem_region.c51
-rw-r--r--include/mem_region.h3
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(&regions, 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);