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 |
New patch | |||
---|---|---|---|
1 | Subject: [PATCH for 6.2?] gicv3: fix ICH_MISR's LRENP computation | 1 | The only remaining caller is riscv_load_kernel_and_initrd() which |
2 | belongs to the same file. | ||
2 | 3 | ||
3 | According to the "Arm Generic Interrupt Controller Architecture | 4 | Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> |
4 | Specification GIC architecture version 3 and 4" (version G: page 345 | 5 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> |
5 | for aarch64 or 509 for aarch32): | 6 | Reviewed-by: Bin Meng <bmeng@tinylab.org> |
6 | LRENP bit of ICH_MISR is set when ICH_HCR.LRENPIE==1 and | 7 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> |
7 | ICH_HCR.EOIcount is non-zero. | 8 | --- |
9 | hw/riscv/boot.c | 80 ++++++++++++++++++++--------------------- | ||
10 | include/hw/riscv/boot.h | 1 - | ||
11 | 2 files changed, 40 insertions(+), 41 deletions(-) | ||
8 | 12 | ||
9 | When only LRENPIE was set (and EOI count was zero), the LRENP bit was | 13 | diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c |
10 | wrongly set and MISR value was wrong. | ||
11 | |||
12 | As an additional consequence, if an hypervisor set ICH_HCR.LRENPIE, | ||
13 | the maintenance interrupt was constantly fired. It happens since patch | ||
14 | 9cee1efe92 ("hw/intc: Set GIC maintenance interrupt level to only 0 or 1") | ||
15 | which fixed another bug about maintenance interrupt (most significant | ||
16 | bits of misr, including this one, were ignored in the interrupt trigger). | ||
17 | |||
18 | Fixes: 83f036fe3d ("hw/intc/arm_gicv3: Add accessors for ICH_ system registers") | ||
19 | Signed-off-by: Damien Hedde <damien.hedde@greensocs.com> | ||
20 | --- | ||
21 | The gic doc is available here: | ||
22 | https://developer.arm.com/documentation/ihi0069/g | ||
23 | --- | ||
24 | hw/intc/arm_gicv3_cpuif.c | 3 ++- | ||
25 | 1 file changed, 2 insertions(+), 1 deletion(-) | ||
26 | |||
27 | diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c | ||
28 | index XXXXXXX..XXXXXXX 100644 | 14 | index XXXXXXX..XXXXXXX 100644 |
29 | --- a/hw/intc/arm_gicv3_cpuif.c | 15 | --- a/hw/riscv/boot.c |
30 | +++ b/hw/intc/arm_gicv3_cpuif.c | 16 | +++ b/hw/riscv/boot.c |
31 | @@ -XXX,XX +XXX,XX @@ static uint32_t maintenance_interrupt_state(GICv3CPUState *cs) | 17 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename, |
32 | /* Scan list registers and fill in the U, NP and EOI bits */ | 18 | exit(1); |
33 | eoi_maintenance_interrupt_state(cs, &value); | 19 | } |
34 | 20 | ||
35 | - if (cs->ich_hcr_el2 & (ICH_HCR_EL2_LRENPIE | ICH_HCR_EL2_EOICOUNT_MASK)) { | 21 | +static void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry) |
36 | + if ((cs->ich_hcr_el2 & ICH_HCR_EL2_LRENPIE) && | 22 | +{ |
37 | + (cs->ich_hcr_el2 & ICH_HCR_EL2_EOICOUNT_MASK)) { | 23 | + const char *filename = machine->initrd_filename; |
38 | value |= ICH_MISR_EL2_LRENP; | 24 | + uint64_t mem_size = machine->ram_size; |
39 | } | 25 | + void *fdt = machine->fdt; |
40 | 26 | + hwaddr start, end; | |
27 | + ssize_t size; | ||
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); | ||
41 | -- | 123 | -- |
42 | 2.34.0 | 124 | 2.39.1 |
43 | 125 | ||
44 | 126 | diff view generated by jsdifflib |