[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH 08/15] x86/hyperlaunch: locate dom0 kernel with hyperlaunch
On 11.12.2024 16:41, Daniel P. Smith wrote: > On 12/2/24 06:53, Jan Beulich wrote: >> On 23.11.2024 19:20, Daniel P. Smith wrote: >>> Look for a subnode of type `multiboot,kernel` within a domain node. If >>> found, >>> process the reg property for the MB1 module index. If the bootargs property >>> is >>> present and there was not an MB1 string, then use the command line from the >>> device tree definition. >> >> Why specifically MB1? > > Because Xen converts MB2 into an MB1 chain very early in the entry > points that take MB2. By the time HL code is executed, it will only ever > see a list of MB1 modules. Yet that's all Xen's internal representation, which merely is kind of originating from MB1. That origin is, afaict, irrelevant here, and is instead, imo, confusing. >>> --- a/xen/arch/x86/domain_builder/fdt.c >>> +++ b/xen/arch/x86/domain_builder/fdt.c >>> @@ -14,6 +14,122 @@ >>> >>> #include "fdt.h" >>> >>> +static inline int __init fdt_get_prop_as_reg( >> >> What does "reg" stand for here? > > Device Tree defines a two field "prop-encoded=array" property type > called reg. Okay, this explains where you took it from, yet I remain curious what it actually stands for. Just from the letters I would derive "register", yet that seems unlikely here. >>> + const void *fdt, int node, const char *name, unsigned int ssize, >>> + unsigned int asize, uint64_t *size, uint64_t *addr) >>> +{ >>> + int ret; >>> + const struct fdt_property *prop; >>> + fdt32_t *cell; >>> + >>> + /* FDT spec max size is 4 (128bit int), but largest arch int size is >>> 64 */ >>> + if ( ssize > 2 || asize > 2 ) >>> + return -EINVAL; >>> + >>> + prop = fdt_get_property(fdt, node, name, &ret); >>> + if ( !prop || ret < sizeof(u32) ) >>> + return ret < 0 ? ret : -EINVAL; >>> + >>> + /* read address field */ >>> + cell = (fdt32_t *)prop->data; >>> + >>> + if ( asize == 1 ) >>> + { >>> + uint32_t val; >>> + fdt_cell_as_u32(cell, &val); >>> + *addr = (uint64_t)val; >> >> No need for a cast here nor ... >> >>> + } >>> + else >>> + fdt_cell_as_u64(cell, addr); >>> + >>> + /* read size field */ >>> + cell += asize; >>> + >>> + if ( ssize == 1 ) >>> + { >>> + uint32_t val; >>> + fdt_cell_as_u32(cell, &val); >>> + *size = (uint64_t)val; >> >> ... here? > > No the compiler does not need the cast, placed to remind readers what > was being done. Can/will drop. > >>> + } >>> + else >>> + fdt_cell_as_u64(cell, size); >>> + >>> + return 0; >>> +} >> >> This whole function reads very much like a library one. Does it really need >> adding here, rather than to the FDT library code we already have? In any >> event there's nothing x86-specific about it, afaics. > > This is where it gets complicated. Most of the higher order functions > exposed by xen/device_tree.h are written to work with FDT indexing > structures, referred to as the unflattened tree. Deconflicting the mixed > use of FDT and FDT index in device_tree.h is beyond the scope of this > series. Going that far also wasn't my request. Yet it's still library-like code, which seems odd to introduce as x86-specific when later it may very well want using by other architectures as well. If the FDT library code isn't a good place, then put it somewhere under xen/lib/? >>> + &size, &addr); >>> + /* An FDT error value may have been returned, translate to -EINVAL */ >>> + if ( ret < 0 ) >>> + return -EINVAL; >>> + >>> + if ( size != 0 ) >>> + return -EOPNOTSUPP; >> >> Not knowing much about DT: What does 0 represent here? > > The libfdt code treats 0 as a valid value, whether zero is a valid value > is driven by the contextual usage of the property. And 0 is the _only_ valid value here? Another comment may be on order, to at least briefly indicate why this is. >>> + if ( addr > MAX_NR_BOOTMODS ) >>> + return -ERANGE; >>> + >>> + /* >>> + * MAX_NR_BOOTMODS cannot exceed the max for MB1, represented by a u32, >>> + * thus the cast down to a u32 will be safe due to the prior check. >>> + */ >>> + return (int)addr; >> >> Comment and cast contradict one another. DYM u32 (really: uint32_t), or plain >> int? If you mean to return a plain int (for the sake of the -errno values >> further up), MAX_NR_BOOTMODS needs to stay below 2**31. > > Good point, we cannot artificially impose 2^31 limit when 2^32 is the > legitimate upper bound supported by the MB1 protocol. Even if that value > is impractical. At the same time, it is beneficial to be able to > communicate failures along with some delineation of the failure. Let me > think about this, and in the meantime suggestions are welcomed. BUILD_BUG_ON(MAX_NR_BOOTMODS > INT_MAX); deferring the thinking about the "bigger than this" aspect until a (perhaps much) later time? >>> +static int __init process_domain_node( >>> + struct boot_info *bi, void *fdt, int dom_node) >>> +{ >>> + int node; >>> + struct boot_domain *bd = &bi->domains[bi->nr_domains]; >>> + const char *name = fdt_get_name(fdt, dom_node, NULL); >>> + int address_size = fdt_address_cells(fdt, dom_node); >>> + int size_size = fdt_size_cells(fdt, dom_node); >>> + >>> + if ( address_size < 0 || size_size < 0 ) >>> + { >>> + printk(" failed processing #address or #size for domain %s)\n", >>> + name == NULL ? "unknown" : name); >>> + return -EINVAL; >>> + } >>> + >>> + fdt_for_each_subnode(node, fdt, dom_node) >>> + { >>> + if ( fdt_node_check_compatible(fdt, node, "multiboot,kernel") == 0 >>> ) >>> + { >>> + int idx = dom0less_module_node(fdt, node, size_size, >>> address_size); >>> + if ( idx < 0 ) >>> + { >>> + printk(" failed processing kernel module for domain >>> %s)\n", >>> + name == NULL ? "unknown" : name); >>> + return idx; >>> + } >>> + >>> + if ( idx > bi->nr_modules ) >>> + { >>> + printk(" invalid kernel module index for domain node >>> (%d)\n", >>> + bi->nr_domains); >>> + return -EINVAL; >>> + } >>> + >>> + printk(" kernel: boot module %d\n", idx); >>> + bi->mods[idx].type = BOOTMOD_KERNEL; >>> + bd->kernel = &bi->mods[idx]; >>> + } >>> + } >> >> What if you find two? > > No different than if someone accidentally duplicated the module line for > the kernel in grub.cfg. It's a violation of the boot convention with the > resulting behavior being indeterminate, which may or may not result in > failure/panic when the domain attempts to boot. It might be worth adding > a warning if a duplicate kernel entry is detected. It is possible that > such a configuration would boot if it was a duplicate paste situation. > So I would not feel right panicking, when there is a possibility that > the configuration could boot. I agree with not panic()ing, and I didn't mean to ask that you do so. A warning ought to be enough indeed. Jan
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |