Skip to content

Commit 69a0ce3

Browse files
wkozaczuknyh
authored andcommitted
arm: do not relocate DTB, instead read it ahead of time
As noted in one of the email threads, the aarch64 build of OSv fails to boot with the following error: "dtb_setup: failed to move dtb (dtb too large?)". It turns out that the dtb ("Device Tree Blob") provided by QEMU is 1MB in size which is far larger that the 64K buffer reserved at the beginning OSV_KERNEL_BASE address. Because of this, the fdt_move() call to relocate (copy) dtb from the original place to the reserved buffer fails. It could be that in early days dtb might have been small enough to fit into 64K area and fdt_move() would succeed. It is also not clear why dtb had to relocated in first place. Possibly it was done because the memory where dtb was originally located would not be unavailable (not mapped) after switching to runtime page tables. One way to fix this error would be to increase the buffer to 1MB. But what if that will not be enough in future. Another way is to not relocate dtb at all and simply pre-read the configuration values from original dtb and store them in known variables so they can be accessed as needed without having to read from dtb later. So this patch modifies the dtb contructor function in arch-dtb.cc to parse following configuration values from dtb: - dtb_cpu_count - dtb_cpus_mpids - dtb_timer_irq - dtb_pci_irqmask - dtb_pci_irqmap_count - dtb_pci_bdfs - dtb_pci_irq_ids It also modifies relevant dtb_get_* functions to simply return the values of the variables above to the caller instead of parsing them from dtb. This patch is enough to make OSv aarch64 build and boot again. This has only been tested on Fedora 29. ./scripts/build -j4 image=native-example fs=ramfs arch=aarch64 qemu-system-aarch64 -s -nographic -machine virt \ -machine gic-version=2 -kernel ./build/release.aarch64/loader.img \ -cpu cortex-a57 -m 1024M \ -append "--verbose --nomount --maxnic=0 /tools/uush.so" -smp 2 Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com> Message-Id: <20191231030407.8641-1-jwkozaczuk@gmail.com>
1 parent 7230f35 commit 69a0ce3

File tree

2 files changed

+75
-16
lines changed

2 files changed

+75
-16
lines changed

arch/aarch64/arch-dtb.cc

Lines changed: 72 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,8 @@ u64 dtb_get_uart(int *irqid)
192192
/* this gets the virtual timer irq, we are not interested
193193
* about the other timers.
194194
*/
195-
196-
int dtb_get_timer_irq()
195+
static int dtb_timer_irq = -1;
196+
static int dtb_parse_timer_irq()
197197
{
198198
int node;
199199
struct dtb_int_spec int_spec[4];
@@ -211,6 +211,11 @@ int dtb_get_timer_irq()
211211
return int_spec[2].irq_id;
212212
}
213213

214+
int dtb_get_timer_irq()
215+
{
216+
return dtb_timer_irq;
217+
}
218+
214219
/* this gets the GIC distributor and cpu interface addresses */
215220
bool dtb_get_gic_v2(u64 *dist, size_t *dist_len, u64 *cpu, size_t *cpu_len)
216221
{
@@ -236,7 +241,8 @@ bool dtb_get_gic_v2(u64 *dist, size_t *dist_len, u64 *cpu, size_t *cpu_len)
236241
}
237242

238243
/* this gets the cpus node and returns the number of cpu elements in it. */
239-
int dtb_get_cpus_count()
244+
static int dtb_cpu_count = -1;
245+
static int dtb_parse_cpus_count()
240246
{
241247
int node, subnode, count;
242248
if (!dtb)
@@ -253,11 +259,22 @@ int dtb_get_cpus_count()
253259
return count;
254260
}
255261

262+
int dtb_get_cpus_count()
263+
{
264+
return dtb_cpu_count;
265+
}
266+
256267
/* this gets the cpu mpidr values for all cpus */
257-
bool dtb_get_cpus_mpid(u64 *mpids, int n)
268+
#define DTB_MAX_CPU_COUNT 32
269+
static u64 dtb_cpus_mpids[DTB_MAX_CPU_COUNT];
270+
bool dtb_parse_cpus_mpid(u64 *mpids, int n)
258271
{
259272
int node, subnode;
260273

274+
if (n > DTB_MAX_CPU_COUNT) {
275+
abort("dtb_parse_cpus_mpid: number of cpus greater than maximum. Increase the DTB_MAX_CPU_COUNT!\n");
276+
}
277+
261278
if (!dtb)
262279
return false;
263280

@@ -274,6 +291,13 @@ bool dtb_get_cpus_mpid(u64 *mpids, int n)
274291
return true;
275292
}
276293

294+
bool dtb_get_cpus_mpid(u64 *mpids, int n) {
295+
for (auto i = 0; i < n; i++) {
296+
mpids[i] = dtb_cpus_mpids[i];
297+
}
298+
return true;
299+
}
300+
277301
static int dtb_get_pci_node()
278302
{
279303
if (dtb_pci_node >= 0) {
@@ -387,7 +411,8 @@ static int dtb_get_pua_cells(u32 phandle)
387411
}
388412

389413
/* get the number of mappings between pci devices and platform IRQs. */
390-
int dtb_get_pci_irqmap_count()
414+
static int dtb_pci_irqmap_count = -1;
415+
static int dtb_parse_pci_irqmap_count()
391416
{
392417
int count;
393418
if (!dtb)
@@ -426,8 +451,14 @@ int dtb_get_pci_irqmap_count()
426451
return count;
427452
}
428453

454+
int dtb_get_pci_irqmap_count()
455+
{
456+
return dtb_pci_irqmap_count;
457+
}
458+
429459
/* gets the mask for just the slot member of the pci address. */
430-
u32 dtb_get_pci_irqmask()
460+
static int dtb_pci_irqmask = -1;
461+
u32 dtb_parse_pci_irqmask()
431462
{
432463
u32 *prop;
433464
int node, size;
@@ -450,8 +481,20 @@ u32 dtb_get_pci_irqmask()
450481
return (fdt32_to_cpu(prop[0]) & DTB_PHYSHI_BDF_MASK) | DTB_PIN_MASK;
451482
}
452483

453-
bool dtb_get_pci_irqmap(u32 *bdfs, int *irq_ids, int n)
484+
u32 dtb_get_pci_irqmask()
454485
{
486+
return dtb_pci_irqmask;
487+
}
488+
489+
#define DTB_MAX_IRQ_COUNT 32
490+
static u32 dtb_pci_bdfs[DTB_MAX_IRQ_COUNT];
491+
static int dtb_pci_irq_ids[DTB_MAX_IRQ_COUNT];
492+
static bool dtb_parse_pci_irqmap(u32 *bdfs, int *irq_ids, int n)
493+
{
494+
if (n > DTB_MAX_IRQ_COUNT) {
495+
abort("dtb_parse_pci_irqmap: number of iqrs greater than maximum. Increase the DTB_MAX_IRQ_COUNT!\n");
496+
}
497+
455498
if (!dtb)
456499
return false;
457500

@@ -502,6 +545,15 @@ bool dtb_get_pci_irqmap(u32 *bdfs, int *irq_ids, int n)
502545
return true;
503546
}
504547

548+
bool dtb_get_pci_irqmap(u32 *bdfs, int *irq_ids, int n)
549+
{
550+
for (auto i = 0; i < n; i++) {
551+
bdfs[i] = dtb_pci_bdfs[i];
552+
irq_ids[i] = dtb_pci_irq_ids[i];
553+
}
554+
return true;
555+
}
556+
505557
bool dtb_get_vmm_is_xen()
506558
{
507559
if (fdt_check_header(dtb) != 0)
@@ -512,7 +564,6 @@ bool dtb_get_vmm_is_xen()
512564

513565
void __attribute__((constructor(init_prio::dtb))) dtb_setup()
514566
{
515-
void *olddtb;
516567
int node;
517568
char *cmdline_override;
518569
int len;
@@ -551,17 +602,24 @@ void __attribute__((constructor(init_prio::dtb))) dtb_setup()
551602
if ((size_t)len > max_cmdline) {
552603
abort("dtb_setup: command line too long.\n");
553604
}
554-
olddtb = dtb;
555-
dtb = (void *)OSV_KERNEL_BASE;
556-
557-
if (fdt_move(olddtb, dtb, 0x10000) != 0) {
558-
abort("dtb_setup: failed to move dtb (dtb too large?)\n");
559-
}
560605

561606
cmdline = (char *)fdt_getprop(dtb, node, "bootargs", NULL);
562607
if (!cmdline) {
563608
abort("dtb_setup: cannot find cmdline after dtb move.\n");
564609
}
610+
// Parse some dtb configuration ahead of time
611+
dtb_cpu_count = dtb_parse_cpus_count();
612+
if (!dtb_parse_cpus_mpid(dtb_cpus_mpids, dtb_cpu_count)) {
613+
abort("dtb_setup: failed to parse cpu mpid.\n");
614+
}
615+
616+
dtb_timer_irq = dtb_parse_timer_irq();
617+
dtb_pci_irqmask = dtb_parse_pci_irqmask();
618+
dtb_pci_irqmap_count = dtb_parse_pci_irqmap_count();
619+
if (!dtb_parse_pci_irqmap(dtb_pci_bdfs, dtb_pci_irq_ids, dtb_pci_irqmap_count)) {
620+
abort("dtb_setup: failed to parse pci_irq_map.\n");
621+
}
622+
565623
register u64 edata;
566624
asm volatile ("adrp %0, .edata" : "=r"(edata));
567625

arch/aarch64/arch-setup.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,10 @@ void arch_setup_free_memory()
112112

113113
arch_setup_pci();
114114

115-
mmu::switch_to_runtime_page_tables();
116-
115+
// get rid of the command line, before memory is unmapped
117116
osv::parse_cmdline(cmdline);
117+
118+
mmu::switch_to_runtime_page_tables();
118119
}
119120

120121
void arch_setup_tls(void *tls, const elf::tls_data& info)

0 commit comments

Comments
 (0)