1 | Fix a bug introduced with dynamic TLB sizing -- we forgot to account | 1 | Hi, |
---|---|---|---|
2 | for possible TLB resizes during tlb_fill(). | ||
3 | 2 | ||
4 | Max reported the bug and provided a reproducer here: | 3 | This new version removed the translate_fn() from patch 1 because it |
5 | https://lists.gnu.org/archive/html/qemu-devel/2019-02/msg02283.html | 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 | 6 | ||
7 | Thanks, | 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. | ||
8 | 10 | ||
9 | Emilio | 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. | ||
10 | 14 | ||
15 | Patches are based on current riscv-to-apply.next. | ||
11 | 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 | ||
12 | 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 |
1 | We are failing to take into account that tlb_fill() can cause a | 1 | load_elf_ram_sym() will sign-extend 32 bit addresses. If a 32 bit QEMU |
---|---|---|---|
2 | TLB resize, which renders prior TLB entry pointers/indices stale. | 2 | guest happens to be running in a hypervisor that are using 64 bits to |
3 | Fix it by re-doing the TLB entry lookups immediately after tlb_fill. | 3 | encode its address, kernel_entry can be padded with '1's and create |
4 | problems [1]. | ||
4 | 5 | ||
5 | Fixes: 86e1eff8bc ("tcg: introduce dynamic TLB sizing", 2019-01-28) | 6 | Using a translate_fn() callback in load_elf_ram_sym() to filter the |
6 | Reported-by: Max Filippov <jcmvbkbc@gmail.com> | 7 | padding from the address doesn't work. A more detailed explanation can |
7 | Tested-by: Max Filippov <jcmvbkbc@gmail.com> | 8 | be found in [2]. The short version is that glue(load_elf, SZ), from |
8 | Signed-off-by: Emilio G. Cota <cota@braap.org> | 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> | ||
9 | --- | 22 | --- |
10 | accel/tcg/softmmu_template.h | 8 ++++++++ | 23 | hw/riscv/boot.c | 15 +++++++++++---- |
11 | accel/tcg/cputlb.c | 4 ++++ | 24 | hw/riscv/microchip_pfsoc.c | 3 ++- |
12 | 2 files changed, 12 insertions(+) | 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(-) | ||
13 | 32 | ||
14 | diff --git a/accel/tcg/softmmu_template.h b/accel/tcg/softmmu_template.h | 33 | diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c |
15 | index XXXXXXX..XXXXXXX 100644 | 34 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/accel/tcg/softmmu_template.h | 35 | --- a/hw/riscv/boot.c |
17 | +++ b/accel/tcg/softmmu_template.h | 36 | +++ b/hw/riscv/boot.c |
18 | @@ -XXX,XX +XXX,XX @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, | 37 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename, |
19 | if (!VICTIM_TLB_HIT(ADDR_READ, addr)) { | 38 | } |
20 | tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, READ_ACCESS_TYPE, | 39 | |
21 | mmu_idx, retaddr); | 40 | target_ulong riscv_load_kernel(MachineState *machine, |
22 | + index = tlb_index(env, mmu_idx, addr); | 41 | + RISCVHartArrayState *harts, |
23 | + entry = tlb_entry(env, mmu_idx, addr); | 42 | target_ulong kernel_start_addr, |
24 | } | 43 | symbol_fn_t sym_cb) |
25 | tlb_addr = entry->ADDR_READ; | 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; | ||
26 | } | 68 | } |
27 | @@ -XXX,XX +XXX,XX @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, | 69 | |
28 | if (!VICTIM_TLB_HIT(ADDR_READ, addr)) { | 70 | if (load_uimage_as(kernel_filename, &kernel_entry, NULL, NULL, |
29 | tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, READ_ACCESS_TYPE, | 71 | diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c |
30 | mmu_idx, retaddr); | 72 | index XXXXXXX..XXXXXXX 100644 |
31 | + index = tlb_index(env, mmu_idx, addr); | 73 | --- a/hw/riscv/microchip_pfsoc.c |
32 | + entry = tlb_entry(env, mmu_idx, addr); | 74 | +++ b/hw/riscv/microchip_pfsoc.c |
33 | } | 75 | @@ -XXX,XX +XXX,XX @@ static void microchip_icicle_kit_machine_init(MachineState *machine) |
34 | tlb_addr = entry->ADDR_READ; | 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) | ||
35 | } | 90 | } |
36 | @@ -XXX,XX +XXX,XX @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, | 91 | |
37 | if (!VICTIM_TLB_HIT(addr_write, addr)) { | 92 | if (machine->kernel_filename) { |
38 | tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE, | 93 | - riscv_load_kernel(machine, memmap[IBEX_DEV_RAM].base, NULL); |
39 | mmu_idx, retaddr); | 94 | + riscv_load_kernel(machine, &s->soc.cpus, |
40 | + index = tlb_index(env, mmu_idx, addr); | 95 | + memmap[IBEX_DEV_RAM].base, NULL); |
41 | + entry = tlb_entry(env, mmu_idx, addr); | ||
42 | } | ||
43 | tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK; | ||
44 | } | 96 | } |
45 | @@ -XXX,XX +XXX,XX @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, | 97 | } |
46 | if (!VICTIM_TLB_HIT(addr_write, addr)) { | 98 | |
47 | tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE, | 99 | diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c |
48 | mmu_idx, retaddr); | 100 | index XXXXXXX..XXXXXXX 100644 |
49 | + index = tlb_index(env, mmu_idx, addr); | 101 | --- a/hw/riscv/sifive_e.c |
50 | + entry = tlb_entry(env, mmu_idx, addr); | 102 | +++ b/hw/riscv/sifive_e.c |
51 | } | 103 | @@ -XXX,XX +XXX,XX @@ static void sifive_e_machine_init(MachineState *machine) |
52 | tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK; | 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); | ||
53 | } | 110 | } |
54 | diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c | 111 | } |
112 | |||
113 | diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c | ||
55 | index XXXXXXX..XXXXXXX 100644 | 114 | index XXXXXXX..XXXXXXX 100644 |
56 | --- a/accel/tcg/cputlb.c | 115 | --- a/hw/riscv/sifive_u.c |
57 | +++ b/accel/tcg/cputlb.c | 116 | +++ b/hw/riscv/sifive_u.c |
58 | @@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr) | 117 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine) |
59 | if (unlikely(!tlb_hit(entry->addr_code, addr))) { | 118 | kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc.u_cpus, |
60 | if (!VICTIM_TLB_HIT(addr_code, addr)) { | 119 | firmware_end_addr); |
61 | tlb_fill(ENV_GET_CPU(env), addr, 0, MMU_INST_FETCH, mmu_idx, 0); | 120 | |
62 | + index = tlb_index(env, mmu_idx, addr); | 121 | - kernel_entry = riscv_load_kernel(machine, kernel_start_addr, NULL); |
63 | + entry = tlb_entry(env, mmu_idx, addr); | 122 | + kernel_entry = riscv_load_kernel(machine, &s->soc.u_cpus, |
64 | } | 123 | + kernel_start_addr, NULL); |
65 | assert(tlb_hit(entry->addr_code, addr)); | 124 | |
66 | } | 125 | if (machine->initrd_filename) { |
67 | @@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr, | 126 | riscv_load_initrd(machine, kernel_entry); |
68 | if (!VICTIM_TLB_HIT(addr_write, addr)) { | 127 | diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c |
69 | tlb_fill(ENV_GET_CPU(env), addr, 1 << s_bits, MMU_DATA_STORE, | 128 | index XXXXXXX..XXXXXXX 100644 |
70 | mmu_idx, retaddr); | 129 | --- a/hw/riscv/spike.c |
71 | + index = tlb_index(env, mmu_idx, addr); | 130 | +++ b/hw/riscv/spike.c |
72 | + tlbe = tlb_entry(env, mmu_idx, addr); | 131 | @@ -XXX,XX +XXX,XX @@ static void spike_board_init(MachineState *machine) |
73 | } | 132 | kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0], |
74 | tlb_addr = tlb_addr_write(tlbe) & ~TLB_INVALID_MASK; | 133 | firmware_end_addr); |
75 | } | 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); | ||
76 | -- | 167 | -- |
77 | 2.17.1 | 168 | 2.39.1 |
78 | |||
79 | 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 | Signed-off-by: Emilio G. Cota <cota@braap.org> | 1 | The only remaining caller is riscv_load_kernel_and_initrd() which |
---|---|---|---|
2 | belongs to the same file. | ||
3 | |||
4 | Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> | ||
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> | ||
2 | --- | 8 | --- |
3 | include/exec/exec-all.h | 5 +++++ | 9 | hw/riscv/boot.c | 80 ++++++++++++++++++++--------------------- |
4 | 1 file changed, 5 insertions(+) | 10 | include/hw/riscv/boot.h | 1 - |
11 | 2 files changed, 40 insertions(+), 41 deletions(-) | ||
5 | 12 | ||
6 | diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h | 13 | diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c |
7 | index XXXXXXX..XXXXXXX 100644 | 14 | index XXXXXXX..XXXXXXX 100644 |
8 | --- a/include/exec/exec-all.h | 15 | --- a/hw/riscv/boot.c |
9 | +++ b/include/exec/exec-all.h | 16 | +++ b/hw/riscv/boot.c |
10 | @@ -XXX,XX +XXX,XX @@ static inline void assert_no_pages_locked(void) | 17 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename, |
11 | struct MemoryRegionSection *iotlb_to_section(CPUState *cpu, | 18 | exit(1); |
12 | hwaddr index, MemTxAttrs attrs); | 19 | } |
13 | 20 | ||
14 | +/* | 21 | +static void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry) |
15 | + * Note: tlb_fill() can trigger a resize of the TLB. This means that all of the | 22 | +{ |
16 | + * caller's prior references to the TLB table (e.g. CPUTLBEntry pointers) must | 23 | + const char *filename = machine->initrd_filename; |
17 | + * be discarded and looked up again (e.g. via tlb_entry()). | 24 | + uint64_t mem_size = machine->ram_size; |
18 | + */ | 25 | + void *fdt = machine->fdt; |
19 | void tlb_fill(CPUState *cpu, target_ulong addr, int size, | 26 | + hwaddr start, end; |
20 | MMUAccessType access_type, int mmu_idx, uintptr_t retaddr); | 27 | + ssize_t size; |
21 | 28 | + | |
29 | + g_assert(filename != NULL); | ||
30 | + | ||
31 | + /* | ||
32 | + * We want to put the initrd far enough into RAM that when the | ||
33 | + * kernel is uncompressed it will not clobber the initrd. However | ||
34 | + * on boards without much RAM we must ensure that we still leave | ||
35 | + * enough room for a decent sized initrd, and on boards with large | ||
36 | + * amounts of RAM we must avoid the initrd being so far up in RAM | ||
37 | + * that it is outside lowmem and inaccessible to the kernel. | ||
38 | + * So for boards with less than 256MB of RAM we put the initrd | ||
39 | + * halfway into RAM, and for boards with 256MB of RAM or more we put | ||
40 | + * the initrd at 128MB. | ||
41 | + */ | ||
42 | + start = kernel_entry + MIN(mem_size / 2, 128 * MiB); | ||
43 | + | ||
44 | + size = load_ramdisk(filename, start, mem_size - start); | ||
45 | + if (size == -1) { | ||
46 | + size = load_image_targphys(filename, start, mem_size - start); | ||
47 | + if (size == -1) { | ||
48 | + error_report("could not load ramdisk '%s'", filename); | ||
49 | + exit(1); | ||
50 | + } | ||
51 | + } | ||
52 | + | ||
53 | + /* Some RISC-V machines (e.g. opentitan) don't have a fdt. */ | ||
54 | + if (fdt) { | ||
55 | + end = start + size; | ||
56 | + qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", start); | ||
57 | + qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", end); | ||
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); | ||
22 | -- | 123 | -- |
23 | 2.17.1 | 124 | 2.39.1 |
24 | 125 | ||
25 | 126 | diff view generated by jsdifflib |