New patch | |||
---|---|---|---|
1 | Hi, | ||
1 | 2 | ||
3 | This new version removed the translate_fn() from patch 1 because it | ||
4 | wasn't removing the sign-extension for pentry as we thought it would. | ||
5 | A more detailed explanation is given in the commit msg of patch 1. | ||
6 | |||
7 | We're now retrieving the 'lowaddr' value from load_elf_ram_sym() and | ||
8 | using it when we're running a 32-bit CPU. This worked with 32 bit | ||
9 | 'virt' machine booting with the -kernel option. | ||
10 | |||
11 | If this approach doesn't work for the Xvisor use case, IMO we should | ||
12 | just filter kernel_load_addr bits directly as we were doing a handful of | ||
13 | versions ago. | ||
14 | |||
15 | Patches are based on current riscv-to-apply.next. | ||
16 | |||
17 | Changes from v9: | ||
18 | - patch 1: | ||
19 | - removed the translate_fn() callback | ||
20 | - return 'kernel_low' when running a 32-bit CPU | ||
21 | - v9 link: https://lists.gnu.org/archive/html/qemu-devel/2023-01/msg04509.html | ||
22 | |||
23 | Daniel Henrique Barboza (3): | ||
24 | hw/riscv: handle 32 bit CPUs kernel_addr in riscv_load_kernel() | ||
25 | hw/riscv/boot.c: consolidate all kernel init in riscv_load_kernel() | ||
26 | hw/riscv/boot.c: make riscv_load_initrd() static | ||
27 | |||
28 | hw/riscv/boot.c | 96 +++++++++++++++++++++++--------------- | ||
29 | hw/riscv/microchip_pfsoc.c | 12 +---- | ||
30 | hw/riscv/opentitan.c | 4 +- | ||
31 | hw/riscv/sifive_e.c | 4 +- | ||
32 | hw/riscv/sifive_u.c | 12 +---- | ||
33 | hw/riscv/spike.c | 14 ++---- | ||
34 | hw/riscv/virt.c | 12 +---- | ||
35 | include/hw/riscv/boot.h | 3 +- | ||
36 | 8 files changed, 76 insertions(+), 81 deletions(-) | ||
37 | |||
38 | -- | ||
39 | 2.39.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | load_elf_ram_sym() will sign-extend 32 bit addresses. If a 32 bit QEMU | ||
2 | guest happens to be running in a hypervisor that are using 64 bits to | ||
3 | encode its address, kernel_entry can be padded with '1's and create | ||
4 | problems [1]. | ||
1 | 5 | ||
6 | Using a translate_fn() callback in load_elf_ram_sym() to filter the | ||
7 | padding from the address doesn't work. A more detailed explanation can | ||
8 | be found in [2]. The short version is that glue(load_elf, SZ), from | ||
9 | include/hw/elf_ops.h, will calculate 'pentry' (mapped into the | ||
10 | 'kernel_load_base' var in riscv_load_Kernel()) before using | ||
11 | translate_fn(), and will not recalculate it after executing it. This | ||
12 | means that the callback does not prevent the padding from | ||
13 | kernel_load_base to appear. | ||
14 | |||
15 | Let's instead use a kernel_low var to capture the 'lowaddr' value from | ||
16 | load_elf_ram_sim(), and return it when we're dealing with 32 bit CPUs. | ||
17 | |||
18 | [1] https://lists.gnu.org/archive/html/qemu-devel/2023-01/msg02281.html | ||
19 | [2] https://lists.gnu.org/archive/html/qemu-devel/2023-02/msg00099.html | ||
20 | |||
21 | Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> | ||
22 | --- | ||
23 | hw/riscv/boot.c | 15 +++++++++++---- | ||
24 | hw/riscv/microchip_pfsoc.c | 3 ++- | ||
25 | hw/riscv/opentitan.c | 3 ++- | ||
26 | hw/riscv/sifive_e.c | 3 ++- | ||
27 | hw/riscv/sifive_u.c | 3 ++- | ||
28 | hw/riscv/spike.c | 3 ++- | ||
29 | hw/riscv/virt.c | 3 ++- | ||
30 | include/hw/riscv/boot.h | 1 + | ||
31 | 8 files changed, 24 insertions(+), 10 deletions(-) | ||
32 | |||
33 | diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c | ||
34 | index XXXXXXX..XXXXXXX 100644 | ||
35 | --- a/hw/riscv/boot.c | ||
36 | +++ b/hw/riscv/boot.c | ||
37 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename, | ||
38 | } | ||
39 | |||
40 | target_ulong riscv_load_kernel(MachineState *machine, | ||
41 | + RISCVHartArrayState *harts, | ||
42 | target_ulong kernel_start_addr, | ||
43 | symbol_fn_t sym_cb) | ||
44 | { | ||
45 | const char *kernel_filename = machine->kernel_filename; | ||
46 | - uint64_t kernel_load_base, kernel_entry; | ||
47 | + uint64_t kernel_load_base, kernel_entry, kernel_low; | ||
48 | |||
49 | g_assert(kernel_filename != NULL); | ||
50 | |||
51 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_kernel(MachineState *machine, | ||
52 | * the (expected) load address load address. This allows kernels to have | ||
53 | * separate SBI and ELF entry points (used by FreeBSD, for example). | ||
54 | */ | ||
55 | - if (load_elf_ram_sym(kernel_filename, NULL, NULL, NULL, | ||
56 | - NULL, &kernel_load_base, NULL, NULL, 0, | ||
57 | + if (load_elf_ram_sym(kernel_filename, NULL, NULL, NULL, NULL, | ||
58 | + &kernel_load_base, &kernel_low, NULL, 0, | ||
59 | EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) { | ||
60 | - return kernel_load_base; | ||
61 | + kernel_entry = kernel_load_base; | ||
62 | + | ||
63 | + if (riscv_is_32bit(harts)) { | ||
64 | + kernel_entry = kernel_low; | ||
65 | + } | ||
66 | + | ||
67 | + return kernel_entry; | ||
68 | } | ||
69 | |||
70 | if (load_uimage_as(kernel_filename, &kernel_entry, NULL, NULL, | ||
71 | diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c | ||
72 | index XXXXXXX..XXXXXXX 100644 | ||
73 | --- a/hw/riscv/microchip_pfsoc.c | ||
74 | +++ b/hw/riscv/microchip_pfsoc.c | ||
75 | @@ -XXX,XX +XXX,XX @@ static void microchip_icicle_kit_machine_init(MachineState *machine) | ||
76 | kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc.u_cpus, | ||
77 | firmware_end_addr); | ||
78 | |||
79 | - kernel_entry = riscv_load_kernel(machine, kernel_start_addr, NULL); | ||
80 | + kernel_entry = riscv_load_kernel(machine, &s->soc.u_cpus, | ||
81 | + kernel_start_addr, NULL); | ||
82 | |||
83 | if (machine->initrd_filename) { | ||
84 | riscv_load_initrd(machine, kernel_entry); | ||
85 | diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c | ||
86 | index XXXXXXX..XXXXXXX 100644 | ||
87 | --- a/hw/riscv/opentitan.c | ||
88 | +++ b/hw/riscv/opentitan.c | ||
89 | @@ -XXX,XX +XXX,XX @@ static void opentitan_board_init(MachineState *machine) | ||
90 | } | ||
91 | |||
92 | if (machine->kernel_filename) { | ||
93 | - riscv_load_kernel(machine, memmap[IBEX_DEV_RAM].base, NULL); | ||
94 | + riscv_load_kernel(machine, &s->soc.cpus, | ||
95 | + memmap[IBEX_DEV_RAM].base, NULL); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c | ||
100 | index XXXXXXX..XXXXXXX 100644 | ||
101 | --- a/hw/riscv/sifive_e.c | ||
102 | +++ b/hw/riscv/sifive_e.c | ||
103 | @@ -XXX,XX +XXX,XX @@ static void sifive_e_machine_init(MachineState *machine) | ||
104 | memmap[SIFIVE_E_DEV_MROM].base, &address_space_memory); | ||
105 | |||
106 | if (machine->kernel_filename) { | ||
107 | - riscv_load_kernel(machine, memmap[SIFIVE_E_DEV_DTIM].base, NULL); | ||
108 | + riscv_load_kernel(machine, &s->soc.cpus, | ||
109 | + memmap[SIFIVE_E_DEV_DTIM].base, NULL); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c | ||
114 | index XXXXXXX..XXXXXXX 100644 | ||
115 | --- a/hw/riscv/sifive_u.c | ||
116 | +++ b/hw/riscv/sifive_u.c | ||
117 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine) | ||
118 | kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc.u_cpus, | ||
119 | firmware_end_addr); | ||
120 | |||
121 | - kernel_entry = riscv_load_kernel(machine, kernel_start_addr, NULL); | ||
122 | + kernel_entry = riscv_load_kernel(machine, &s->soc.u_cpus, | ||
123 | + kernel_start_addr, NULL); | ||
124 | |||
125 | if (machine->initrd_filename) { | ||
126 | riscv_load_initrd(machine, kernel_entry); | ||
127 | diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c | ||
128 | index XXXXXXX..XXXXXXX 100644 | ||
129 | --- a/hw/riscv/spike.c | ||
130 | +++ b/hw/riscv/spike.c | ||
131 | @@ -XXX,XX +XXX,XX @@ static void spike_board_init(MachineState *machine) | ||
132 | kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0], | ||
133 | firmware_end_addr); | ||
134 | |||
135 | - kernel_entry = riscv_load_kernel(machine, kernel_start_addr, | ||
136 | + kernel_entry = riscv_load_kernel(machine, &s->soc[0], | ||
137 | + kernel_start_addr, | ||
138 | htif_symbol_callback); | ||
139 | |||
140 | if (machine->initrd_filename) { | ||
141 | diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c | ||
142 | index XXXXXXX..XXXXXXX 100644 | ||
143 | --- a/hw/riscv/virt.c | ||
144 | +++ b/hw/riscv/virt.c | ||
145 | @@ -XXX,XX +XXX,XX @@ static void virt_machine_done(Notifier *notifier, void *data) | ||
146 | kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0], | ||
147 | firmware_end_addr); | ||
148 | |||
149 | - kernel_entry = riscv_load_kernel(machine, kernel_start_addr, NULL); | ||
150 | + kernel_entry = riscv_load_kernel(machine, &s->soc[0], | ||
151 | + kernel_start_addr, NULL); | ||
152 | |||
153 | if (machine->initrd_filename) { | ||
154 | riscv_load_initrd(machine, kernel_entry); | ||
155 | diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h | ||
156 | index XXXXXXX..XXXXXXX 100644 | ||
157 | --- a/include/hw/riscv/boot.h | ||
158 | +++ b/include/hw/riscv/boot.h | ||
159 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename, | ||
160 | hwaddr firmware_load_addr, | ||
161 | symbol_fn_t sym_cb); | ||
162 | target_ulong riscv_load_kernel(MachineState *machine, | ||
163 | + RISCVHartArrayState *harts, | ||
164 | target_ulong firmware_end_addr, | ||
165 | symbol_fn_t sym_cb); | ||
166 | void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry); | ||
167 | -- | ||
168 | 2.39.1 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | 1 | The microchip_icicle_kit, sifive_u, spike and virt boards are now doing | |
2 | the same steps when '-kernel' is used: | ||
3 | |||
4 | - execute load_kernel() | ||
5 | - load init_rd() | ||
6 | - write kernel_cmdline | ||
7 | |||
8 | Let's fold everything inside riscv_load_kernel() to avoid code | ||
9 | repetition. To not change the behavior of boards that aren't calling | ||
10 | riscv_load_init(), add an 'load_initrd' flag to riscv_load_kernel() and | ||
11 | allow these boards to opt out from initrd loading. | ||
12 | |||
13 | Cc: Palmer Dabbelt <palmer@dabbelt.com> | ||
14 | Reviewed-by: Bin Meng <bmeng@tinylab.org> | ||
15 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
16 | Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> | ||
17 | --- | ||
18 | hw/riscv/boot.c | 21 ++++++++++++++++++--- | ||
19 | hw/riscv/microchip_pfsoc.c | 11 +---------- | ||
20 | hw/riscv/opentitan.c | 3 ++- | ||
21 | hw/riscv/sifive_e.c | 3 ++- | ||
22 | hw/riscv/sifive_u.c | 11 +---------- | ||
23 | hw/riscv/spike.c | 11 +---------- | ||
24 | hw/riscv/virt.c | 11 +---------- | ||
25 | include/hw/riscv/boot.h | 1 + | ||
26 | 8 files changed, 27 insertions(+), 45 deletions(-) | ||
27 | |||
28 | diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c | ||
29 | index XXXXXXX..XXXXXXX 100644 | ||
30 | --- a/hw/riscv/boot.c | ||
31 | +++ b/hw/riscv/boot.c | ||
32 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename, | ||
33 | target_ulong riscv_load_kernel(MachineState *machine, | ||
34 | RISCVHartArrayState *harts, | ||
35 | target_ulong kernel_start_addr, | ||
36 | + bool load_initrd, | ||
37 | symbol_fn_t sym_cb) | ||
38 | { | ||
39 | const char *kernel_filename = machine->kernel_filename; | ||
40 | uint64_t kernel_load_base, kernel_entry, kernel_low; | ||
41 | + void *fdt = machine->fdt; | ||
42 | |||
43 | g_assert(kernel_filename != NULL); | ||
44 | |||
45 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_kernel(MachineState *machine, | ||
46 | kernel_entry = kernel_low; | ||
47 | } | ||
48 | |||
49 | - return kernel_entry; | ||
50 | + goto out; | ||
51 | } | ||
52 | |||
53 | if (load_uimage_as(kernel_filename, &kernel_entry, NULL, NULL, | ||
54 | NULL, NULL, NULL) > 0) { | ||
55 | - return kernel_entry; | ||
56 | + goto out; | ||
57 | } | ||
58 | |||
59 | if (load_image_targphys_as(kernel_filename, kernel_start_addr, | ||
60 | current_machine->ram_size, NULL) > 0) { | ||
61 | - return kernel_start_addr; | ||
62 | + kernel_entry = kernel_start_addr; | ||
63 | + goto out; | ||
64 | } | ||
65 | |||
66 | error_report("could not load kernel '%s'", kernel_filename); | ||
67 | exit(1); | ||
68 | + | ||
69 | +out: | ||
70 | + if (load_initrd && machine->initrd_filename) { | ||
71 | + riscv_load_initrd(machine, kernel_entry); | ||
72 | + } | ||
73 | + | ||
74 | + if (fdt && machine->kernel_cmdline && *machine->kernel_cmdline) { | ||
75 | + qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", | ||
76 | + machine->kernel_cmdline); | ||
77 | + } | ||
78 | + | ||
79 | + return kernel_entry; | ||
80 | } | ||
81 | |||
82 | void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry) | ||
83 | diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c | ||
84 | index XXXXXXX..XXXXXXX 100644 | ||
85 | --- a/hw/riscv/microchip_pfsoc.c | ||
86 | +++ b/hw/riscv/microchip_pfsoc.c | ||
87 | @@ -XXX,XX +XXX,XX @@ static void microchip_icicle_kit_machine_init(MachineState *machine) | ||
88 | firmware_end_addr); | ||
89 | |||
90 | kernel_entry = riscv_load_kernel(machine, &s->soc.u_cpus, | ||
91 | - kernel_start_addr, NULL); | ||
92 | - | ||
93 | - if (machine->initrd_filename) { | ||
94 | - riscv_load_initrd(machine, kernel_entry); | ||
95 | - } | ||
96 | - | ||
97 | - if (machine->kernel_cmdline && *machine->kernel_cmdline) { | ||
98 | - qemu_fdt_setprop_string(machine->fdt, "/chosen", | ||
99 | - "bootargs", machine->kernel_cmdline); | ||
100 | - } | ||
101 | + kernel_start_addr, true, NULL); | ||
102 | |||
103 | /* Compute the fdt load address in dram */ | ||
104 | fdt_load_addr = riscv_compute_fdt_addr(memmap[MICROCHIP_PFSOC_DRAM_LO].base, | ||
105 | diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c | ||
106 | index XXXXXXX..XXXXXXX 100644 | ||
107 | --- a/hw/riscv/opentitan.c | ||
108 | +++ b/hw/riscv/opentitan.c | ||
109 | @@ -XXX,XX +XXX,XX @@ static void opentitan_board_init(MachineState *machine) | ||
110 | |||
111 | if (machine->kernel_filename) { | ||
112 | riscv_load_kernel(machine, &s->soc.cpus, | ||
113 | - memmap[IBEX_DEV_RAM].base, NULL); | ||
114 | + memmap[IBEX_DEV_RAM].base, | ||
115 | + false, NULL); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c | ||
120 | index XXXXXXX..XXXXXXX 100644 | ||
121 | --- a/hw/riscv/sifive_e.c | ||
122 | +++ b/hw/riscv/sifive_e.c | ||
123 | @@ -XXX,XX +XXX,XX @@ static void sifive_e_machine_init(MachineState *machine) | ||
124 | |||
125 | if (machine->kernel_filename) { | ||
126 | riscv_load_kernel(machine, &s->soc.cpus, | ||
127 | - memmap[SIFIVE_E_DEV_DTIM].base, NULL); | ||
128 | + memmap[SIFIVE_E_DEV_DTIM].base, | ||
129 | + false, NULL); | ||
130 | } | ||
131 | } | ||
132 | |||
133 | diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c | ||
134 | index XXXXXXX..XXXXXXX 100644 | ||
135 | --- a/hw/riscv/sifive_u.c | ||
136 | +++ b/hw/riscv/sifive_u.c | ||
137 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine) | ||
138 | firmware_end_addr); | ||
139 | |||
140 | kernel_entry = riscv_load_kernel(machine, &s->soc.u_cpus, | ||
141 | - kernel_start_addr, NULL); | ||
142 | - | ||
143 | - if (machine->initrd_filename) { | ||
144 | - riscv_load_initrd(machine, kernel_entry); | ||
145 | - } | ||
146 | - | ||
147 | - if (machine->kernel_cmdline && *machine->kernel_cmdline) { | ||
148 | - qemu_fdt_setprop_string(machine->fdt, "/chosen", "bootargs", | ||
149 | - machine->kernel_cmdline); | ||
150 | - } | ||
151 | + kernel_start_addr, true, NULL); | ||
152 | } else { | ||
153 | /* | ||
154 | * If dynamic firmware is used, it doesn't know where is the next mode | ||
155 | diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c | ||
156 | index XXXXXXX..XXXXXXX 100644 | ||
157 | --- a/hw/riscv/spike.c | ||
158 | +++ b/hw/riscv/spike.c | ||
159 | @@ -XXX,XX +XXX,XX @@ static void spike_board_init(MachineState *machine) | ||
160 | |||
161 | kernel_entry = riscv_load_kernel(machine, &s->soc[0], | ||
162 | kernel_start_addr, | ||
163 | - htif_symbol_callback); | ||
164 | - | ||
165 | - if (machine->initrd_filename) { | ||
166 | - riscv_load_initrd(machine, kernel_entry); | ||
167 | - } | ||
168 | - | ||
169 | - if (machine->kernel_cmdline && *machine->kernel_cmdline) { | ||
170 | - qemu_fdt_setprop_string(machine->fdt, "/chosen", "bootargs", | ||
171 | - machine->kernel_cmdline); | ||
172 | - } | ||
173 | + true, htif_symbol_callback); | ||
174 | } else { | ||
175 | /* | ||
176 | * If dynamic firmware is used, it doesn't know where is the next mode | ||
177 | diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c | ||
178 | index XXXXXXX..XXXXXXX 100644 | ||
179 | --- a/hw/riscv/virt.c | ||
180 | +++ b/hw/riscv/virt.c | ||
181 | @@ -XXX,XX +XXX,XX @@ static void virt_machine_done(Notifier *notifier, void *data) | ||
182 | firmware_end_addr); | ||
183 | |||
184 | kernel_entry = riscv_load_kernel(machine, &s->soc[0], | ||
185 | - kernel_start_addr, NULL); | ||
186 | - | ||
187 | - if (machine->initrd_filename) { | ||
188 | - riscv_load_initrd(machine, kernel_entry); | ||
189 | - } | ||
190 | - | ||
191 | - if (machine->kernel_cmdline && *machine->kernel_cmdline) { | ||
192 | - qemu_fdt_setprop_string(machine->fdt, "/chosen", "bootargs", | ||
193 | - machine->kernel_cmdline); | ||
194 | - } | ||
195 | + kernel_start_addr, true, NULL); | ||
196 | } else { | ||
197 | /* | ||
198 | * If dynamic firmware is used, it doesn't know where is the next mode | ||
199 | diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h | ||
200 | index XXXXXXX..XXXXXXX 100644 | ||
201 | --- a/include/hw/riscv/boot.h | ||
202 | +++ b/include/hw/riscv/boot.h | ||
203 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename, | ||
204 | target_ulong riscv_load_kernel(MachineState *machine, | ||
205 | RISCVHartArrayState *harts, | ||
206 | target_ulong firmware_end_addr, | ||
207 | + bool load_initrd, | ||
208 | symbol_fn_t sym_cb); | ||
209 | void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry); | ||
210 | uint64_t riscv_compute_fdt_addr(hwaddr dram_start, uint64_t dram_size, | ||
211 | -- | ||
212 | 2.39.1 | diff view generated by jsdifflib |
1 | Currently we have both multi-thread compression and multifd to optimize | 1 | The only remaining caller is riscv_load_kernel_and_initrd() which |
---|---|---|---|
2 | live migration in Qemu. Mulit-thread compression deals with the situation | 2 | belongs to the same file. |
3 | where network bandwith is limited but cpu resource adequate. Multifd instead | ||
4 | aims to take full advantage of network bandwith. Moreover it supports both | ||
5 | zlib and zstd compression on each channel. | ||
6 | 3 | ||
7 | In this patch series, we did some code refactoring on multi-thread compression | 4 | Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> |
8 | live migration and bring zstd compression method support for it. | 5 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> |
6 | Reviewed-by: Bin Meng <bmeng@tinylab.org> | ||
7 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
8 | --- | ||
9 | hw/riscv/boot.c | 80 ++++++++++++++++++++--------------------- | ||
10 | include/hw/riscv/boot.h | 1 - | ||
11 | 2 files changed, 40 insertions(+), 41 deletions(-) | ||
9 | 12 | ||
10 | Below is the test result of multi-thread compression live migration | 13 | diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c |
11 | with different compress methods. Test result shows that zstd outperforms | 14 | index XXXXXXX..XXXXXXX 100644 |
12 | zlib by about 70%. | 15 | --- a/hw/riscv/boot.c |
13 | 16 | +++ b/hw/riscv/boot.c | |
14 | Migration Configuration: | 17 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename, |
15 | Guest 8U 32G | 18 | exit(1); |
16 | compress-threads 8 | 19 | } |
17 | decompress-threads 2 | 20 | |
18 | compress-level 1 | 21 | +static void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry) |
19 | bandwidth-limit 100Mbps | 22 | +{ |
20 | 23 | + const char *filename = machine->initrd_filename; | |
21 | Test Result: | 24 | + uint64_t mem_size = machine->ram_size; |
22 | +---------------------+--------------+-------------+ | 25 | + void *fdt = machine->fdt; |
23 | | compress method | zlib | zstd | | 26 | + hwaddr start, end; |
24 | +---------------------+--------------+-------------+ | 27 | + ssize_t size; |
25 | | total time (ms) | 75256 | 44187 | | 28 | + |
26 | +---------------------+--------------+-------------+ | 29 | + g_assert(filename != NULL); |
27 | | downtime(ms) | 128 | 81 | | 30 | + |
28 | +---------------------+--------------+-------------+ | 31 | + /* |
29 | | transferred ram(kB)| 1576866 | 736117 | | 32 | + * We want to put the initrd far enough into RAM that when the |
30 | +---------------------+--------------+-------------+ | 33 | + * kernel is uncompressed it will not clobber the initrd. However |
31 | | throughput(mbps) | 172.06 | 137.16 | | 34 | + * on boards without much RAM we must ensure that we still leave |
32 | +---------------------+--------------+-------------+ | 35 | + * enough room for a decent sized initrd, and on boards with large |
33 | | total ram(kB) | 33685952 | 33685952 | | 36 | + * amounts of RAM we must avoid the initrd being so far up in RAM |
34 | +---------------------+--------------+-------------+ | 37 | + * that it is outside lowmem and inaccessible to the kernel. |
35 | 38 | + * So for boards with less than 256MB of RAM we put the initrd | |
36 | Zeyu Jin (6): | 39 | + * halfway into RAM, and for boards with 256MB of RAM or more we put |
37 | migration: Add multi-thread compress method | 40 | + * the initrd at 128MB. |
38 | migration: Refactoring multi-thread compress migration | 41 | + */ |
39 | migration: Add multi-thread compress ops | 42 | + start = kernel_entry + MIN(mem_size / 2, 128 * MiB); |
40 | migration: Add zstd support in multi-thread compression | 43 | + |
41 | migration: Add compress_level sanity check | 44 | + size = load_ramdisk(filename, start, mem_size - start); |
42 | doc: Update multi-thread compression doc | 45 | + if (size == -1) { |
43 | 46 | + size = load_image_targphys(filename, start, mem_size - start); | |
44 | docs/multi-thread-compression.txt | 31 ++- | 47 | + if (size == -1) { |
45 | hw/core/qdev-properties-system.c | 11 + | 48 | + error_report("could not load ramdisk '%s'", filename); |
46 | include/hw/qdev-properties.h | 4 + | 49 | + exit(1); |
47 | migration/migration.c | 56 ++++- | 50 | + } |
48 | migration/migration.h | 1 + | 51 | + } |
49 | migration/qemu-file.c | 62 +---- | 52 | + |
50 | migration/qemu-file.h | 4 +- | 53 | + /* Some RISC-V machines (e.g. opentitan) don't have a fdt. */ |
51 | migration/ram.c | 381 +++++++++++++++++++++++++----- | 54 | + if (fdt) { |
52 | monitor/hmp-cmds.c | 12 + | 55 | + end = start + size; |
53 | qapi/migration.json | 26 +- | 56 | + qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", start); |
54 | 10 files changed, 465 insertions(+), 123 deletions(-) | 57 | + qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", end); |
55 | 58 | + } | |
59 | +} | ||
60 | + | ||
61 | target_ulong riscv_load_kernel(MachineState *machine, | ||
62 | RISCVHartArrayState *harts, | ||
63 | target_ulong kernel_start_addr, | ||
64 | @@ -XXX,XX +XXX,XX @@ out: | ||
65 | return kernel_entry; | ||
66 | } | ||
67 | |||
68 | -void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry) | ||
69 | -{ | ||
70 | - const char *filename = machine->initrd_filename; | ||
71 | - uint64_t mem_size = machine->ram_size; | ||
72 | - void *fdt = machine->fdt; | ||
73 | - hwaddr start, end; | ||
74 | - ssize_t size; | ||
75 | - | ||
76 | - g_assert(filename != NULL); | ||
77 | - | ||
78 | - /* | ||
79 | - * We want to put the initrd far enough into RAM that when the | ||
80 | - * kernel is uncompressed it will not clobber the initrd. However | ||
81 | - * on boards without much RAM we must ensure that we still leave | ||
82 | - * enough room for a decent sized initrd, and on boards with large | ||
83 | - * amounts of RAM we must avoid the initrd being so far up in RAM | ||
84 | - * that it is outside lowmem and inaccessible to the kernel. | ||
85 | - * So for boards with less than 256MB of RAM we put the initrd | ||
86 | - * halfway into RAM, and for boards with 256MB of RAM or more we put | ||
87 | - * the initrd at 128MB. | ||
88 | - */ | ||
89 | - start = kernel_entry + MIN(mem_size / 2, 128 * MiB); | ||
90 | - | ||
91 | - size = load_ramdisk(filename, start, mem_size - start); | ||
92 | - if (size == -1) { | ||
93 | - size = load_image_targphys(filename, start, mem_size - start); | ||
94 | - if (size == -1) { | ||
95 | - error_report("could not load ramdisk '%s'", filename); | ||
96 | - exit(1); | ||
97 | - } | ||
98 | - } | ||
99 | - | ||
100 | - /* Some RISC-V machines (e.g. opentitan) don't have a fdt. */ | ||
101 | - if (fdt) { | ||
102 | - end = start + size; | ||
103 | - qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", start); | ||
104 | - qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", end); | ||
105 | - } | ||
106 | -} | ||
107 | - | ||
108 | /* | ||
109 | * This function makes an assumption that the DRAM interval | ||
110 | * 'dram_base' + 'dram_size' is contiguous. | ||
111 | diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h | ||
112 | index XXXXXXX..XXXXXXX 100644 | ||
113 | --- a/include/hw/riscv/boot.h | ||
114 | +++ b/include/hw/riscv/boot.h | ||
115 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_kernel(MachineState *machine, | ||
116 | target_ulong firmware_end_addr, | ||
117 | bool load_initrd, | ||
118 | symbol_fn_t sym_cb); | ||
119 | -void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry); | ||
120 | uint64_t riscv_compute_fdt_addr(hwaddr dram_start, uint64_t dram_size, | ||
121 | MachineState *ms); | ||
122 | void riscv_load_fdt(hwaddr fdt_addr, void *fdt); | ||
56 | -- | 123 | -- |
57 | 2.27.0 | 124 | 2.39.1 |
58 | 125 | ||
59 | 126 | diff view generated by jsdifflib |