On 08.04.2025 18:07, Alejandro Vallejo wrote:
> From: "Daniel P. Smith" <dpsm...@apertussolutions.com>
> 
> Add a container for the "cooked" command line for a domain. This
> provides for the backing memory to be directly associated with the
> domain being constructed.  This is done in anticipation that the domain
> construction path may need to be invoked multiple times, thus ensuring
> each instance had a distinct memory allocation.
> 
> Signed-off-by: Daniel P. Smith <dpsm...@apertussolutions.com>
> Signed-off-by: Jason Andryuk <jason.andr...@amd.com>
> Signed-off-by: Alejandro Vallejo <agarc...@amd.com>
> ---
> No changes on ACPI cmdline handling on PVH, as it's orthogonal to the
> purpose of this patch.
> 
> v3:
>   * s/xfree/XFREE/ on failed construct_dom0() to avoid a dangling
> cmdline ptr.
>   * Re-flow hvm_copy_to_guest_phys() into a multi-line call.
>   * s/bd->cmdline != NULL/b->cmdline/ (to homogenise with the previous
>     cmdline pointer check)
> ---
>  xen/arch/x86/hvm/dom0_build.c          | 12 +++----
>  xen/arch/x86/include/asm/boot-domain.h |  1 +
>  xen/arch/x86/pv/dom0_build.c           |  4 +--
>  xen/arch/x86/setup.c                   | 50 +++++++++++++++++++-------
>  4 files changed, 47 insertions(+), 20 deletions(-)
> 
> diff --git a/xen/arch/x86/hvm/dom0_build.c b/xen/arch/x86/hvm/dom0_build.c
> index 2a094b3145..ebad5a49b8 100644
> --- a/xen/arch/x86/hvm/dom0_build.c
> +++ b/xen/arch/x86/hvm/dom0_build.c
> @@ -653,7 +653,6 @@ static int __init pvh_load_kernel(
>      void *image_start = image_base + image->headroom;
>      unsigned long image_len = image->size;
>      unsigned long initrd_len = initrd ? initrd->size : 0;
> -    const char *cmdline = image->cmdline_pa ? __va(image->cmdline_pa) : NULL;
>      const char *initrd_cmdline = NULL;
>      struct elf_binary elf;
>      struct elf_dom_parms parms;
> @@ -736,8 +735,8 @@ static int __init pvh_load_kernel(
>              initrd = NULL;
>      }
>  
> -    if ( cmdline )
> -        extra_space += elf_round_up(&elf, strlen(cmdline) + 1);
> +    if ( bd->cmdline )
> +        extra_space += elf_round_up(&elf, strlen(bd->cmdline) + 1);
>  
>      last_addr = find_memory(d, &elf, extra_space);
>      if ( last_addr == INVALID_PADDR )
> @@ -778,9 +777,10 @@ static int __init pvh_load_kernel(
>      /* Free temporary buffers. */
>      free_boot_modules();
>  
> -    if ( cmdline != NULL )
> +    if ( bd->cmdline )
>      {
> -        rc = hvm_copy_to_guest_phys(last_addr, cmdline, strlen(cmdline) + 1, 
> v);
> +        rc = hvm_copy_to_guest_phys(last_addr, bd->cmdline,
> +                                    strlen(bd->cmdline) + 1, v);
>          if ( rc )
>          {
>              printk("Unable to copy guest command line\n");
> @@ -791,7 +791,7 @@ static int __init pvh_load_kernel(
>           * Round up to 32/64 bits (depending on the guest kernel bitness) so
>           * the modlist/start_info is aligned.
>           */
> -        last_addr += elf_round_up(&elf, strlen(cmdline) + 1);
> +        last_addr += elf_round_up(&elf, strlen(bd->cmdline) + 1);
>      }
>      if ( initrd != NULL )
>      {

Perhaps better introduce a local variable cmdline_len? That would allow the 
first
if() to go away (but of course not its body).

> --- a/xen/arch/x86/setup.c
> +++ b/xen/arch/x86/setup.c
> @@ -978,10 +978,30 @@ static unsigned int __init copy_bios_e820(struct 
> e820entry *map, unsigned int li
>      return n;
>  }
>  
> -static struct domain *__init create_dom0(struct boot_info *bi)
> +static size_t __init domain_cmdline_size(
> +    struct boot_info *bi, struct boot_domain *bd)

const for both? And perhaps s/domain/dom0/ in the function name?

>  {
> -    static char __initdata cmdline[MAX_GUEST_CMDLINE];
> +    size_t s = bi->kextra ? strlen(bi->kextra) : 0;
> +
> +    s += bd->kernel->cmdline_pa ? strlen(__va(bd->kernel->cmdline_pa)) : 0;
>  
> +    if ( s == 0 )
> +        return s;

While this retains prior behavior, that prior behavior was certainly odd (and
pretty likely not meant to be like that).

> @@ -1043,17 +1067,19 @@ static struct domain *__init create_dom0(struct 
> boot_info *bi)
>  
>          if ( (strlen(acpi_param) != 0) && !strstr(cmdline, "acpi=") )
>          {
> -            safe_strcat(cmdline, " acpi=");
> -            safe_strcat(cmdline, acpi_param);
> +            strlcat(cmdline, " acpi=", cmdline_size);
> +            strlcat(cmdline, acpi_param, cmdline_size);
>          }
> -
> -        bd->kernel->cmdline_pa = __pa(cmdline);
> +        bd->kernel->cmdline_pa = 0;
> +        bd->cmdline = cmdline;
>      }
>  
>      bd->d = d;
>      if ( construct_dom0(bd) != 0 )
>          panic("Could not construct domain 0\n");
>  
> +    XFREE(cmdline);

While this tidies the local variable, what about bd->cmdline? As it stands this
gives the impression that you're freeing a pointer here which may still be used
through passing bd elsewhere.

Jan

Reply via email to