diff mbox

[v5,09/11] xen: add capability to load initrd outside of initial mapping

Message ID 1456400017-5789-10-git-send-email-jgross@suse.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jürgen Groß Feb. 25, 2016, 11:33 a.m. UTC
Modern pvops linux kernels support an initrd not covered by the initial
mapping. This capability is flagged by an elf-note.

In case the elf-note is set by the kernel don't place the initrd into
the initial mapping. This will allow to load larger initrds and/or
support domains with larger memory, as the initial mapping is limited
to 2GB and it is containing the p2m list.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
V5: let call grub_xen_alloc_final() all subfunctions unconditionally
    and let them decide whether they need to do anything
V4: rename grub_xen_alloc_end() to grub_xen_alloc_final()
---
 grub-core/loader/i386/xen.c        | 65 ++++++++++++++++++++++++++++++--------
 grub-core/loader/i386/xen_fileXX.c |  3 ++
 include/grub/xen_file.h            |  1 +
 3 files changed, 56 insertions(+), 13 deletions(-)

Comments

Daniel Kiper Feb. 25, 2016, 12:47 p.m. UTC | #1
On Thu, Feb 25, 2016 at 12:33:35PM +0100, Juergen Gross wrote:
> Modern pvops linux kernels support an initrd not covered by the initial
> mapping. This capability is flagged by an elf-note.
>
> In case the elf-note is set by the kernel don't place the initrd into
> the initial mapping. This will allow to load larger initrds and/or
> support domains with larger memory, as the initial mapping is limited
> to 2GB and it is containing the p2m list.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
> V5: let call grub_xen_alloc_final() all subfunctions unconditionally
>     and let them decide whether they need to do anything
> V4: rename grub_xen_alloc_end() to grub_xen_alloc_final()
> ---
>  grub-core/loader/i386/xen.c        | 65 ++++++++++++++++++++++++++++++--------
>  grub-core/loader/i386/xen_fileXX.c |  3 ++
>  include/grub/xen_file.h            |  1 +
>  3 files changed, 56 insertions(+), 13 deletions(-)
>
> diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
> index 2e12763..466f0c0 100644
> --- a/grub-core/loader/i386/xen.c
> +++ b/grub-core/loader/i386/xen.c
> @@ -228,6 +228,9 @@ grub_xen_p2m_alloc (void)
>    grub_size_t p2msize;
>    grub_err_t err;
>
> +  if (xen_state.virt_mfn_list)
> +    return GRUB_ERR_NONE;
> +
>    xen_state.state.mfn_list = xen_state.max_addr;
>    xen_state.next_start.mfn_list =
>      xen_state.max_addr + xen_state.xen_inf.virt_base;
> @@ -250,6 +253,9 @@ grub_xen_special_alloc (void)
>    grub_relocator_chunk_t ch;
>    grub_err_t err;
>
> +  if (xen_state.virt_start_info)
> +    return GRUB_ERR_NONE;
> +
>    err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch,
>  					 xen_state.max_addr,
>  					 sizeof (xen_state.next_start));
> @@ -281,6 +287,9 @@ grub_xen_pt_alloc (void)
>    grub_uint64_t nr_info_pages;
>    grub_uint64_t nr_pages, nr_pt_pages, nr_need_pages;
>
> +  if (xen_state.virt_pgtable)
> +    return GRUB_ERR_NONE;
> +
>    xen_state.next_start.pt_base =
>      xen_state.max_addr + xen_state.xen_inf.virt_base;
>    xen_state.state.paging_start = xen_state.max_addr >> PAGE_SHIFT;
> @@ -320,6 +329,24 @@ grub_xen_pt_alloc (void)
>  }
>
>  static grub_err_t
> +grub_xen_alloc_final (void)
> +{
> +  grub_err_t err;
> +
> +  err = grub_xen_p2m_alloc ();
> +  if (err)
> +    return err;
> +  err = grub_xen_special_alloc ();
> +  if (err)
> +    return err;
> +  err = grub_xen_pt_alloc ();
> +  if (err)
> +    return err;

Could you move grub_xen_p2m_alloc() here? This way grub_xen_alloc_final()
will be real final in patch 11 and you do not need an extra condition
around grub_xen_p2m_alloc().

> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
>  grub_xen_boot (void)
>  {
>    grub_err_t err;
> @@ -330,13 +357,7 @@ grub_xen_boot (void)
>    if (grub_xen_n_allocated_shared_pages)
>      return grub_error (GRUB_ERR_BUG, "active grants");
>
> -  err = grub_xen_p2m_alloc ();
> -  if (err)
> -    return err;
> -  err = grub_xen_special_alloc ();
> -  if (err)
> -    return err;
> -  err = grub_xen_pt_alloc ();
> +  err = grub_xen_alloc_final ();

if (!xen_state.xen_inf.unmapped_initrd)
  {
    err = grub_xen_alloc_final ();
    if (err)
      goto fail;
  }

This way you avoid checks in grub_xen_p2m_alloc(),
grub_xen_special_alloc() and grub_xen_pt_alloc().

>    if (err)
>      return err;
>
> @@ -610,6 +631,13 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
>        goto fail;
>      }
>
> +  if (xen_state.xen_inf.unmapped_initrd)
> +    {
> +      err = grub_xen_alloc_final ();
> +      if (err)
> +	goto fail;
> +    }
> +
>    if (grub_initrd_init (argc, argv, &initrd_ctx))
>      goto fail;
>
> @@ -627,14 +655,24 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
>  	goto fail;
>      }
>
> -  xen_state.next_start.mod_start =
> -    xen_state.max_addr + xen_state.xen_inf.virt_base;
> -  xen_state.next_start.mod_len = size;

Leave "xen_state.next_start.mod_len = size;" as is here and...

> -
> -  xen_state.max_addr = ALIGN_UP (xen_state.max_addr + size, PAGE_SIZE);
> +  if (xen_state.xen_inf.unmapped_initrd)
> +    {
> +      xen_state.next_start.flags |= SIF_MOD_START_PFN;
> +      xen_state.next_start.mod_start = xen_state.max_addr >> PAGE_SHIFT;
> +      xen_state.next_start.mod_len = size;

... do not add it here...

> +    }
> +  else
> +    {
> +      xen_state.next_start.mod_start =
> +	xen_state.max_addr + xen_state.xen_inf.virt_base;
> +      xen_state.next_start.mod_len = size;

... and here...

> +    }

... and you do not need curly brackets then.

>    grub_dprintf ("xen", "Initrd, addr=0x%x, size=0x%x\n",
> -		(unsigned) xen_state.next_start.mod_start, (unsigned) size);
> +		(unsigned) (xen_state.max_addr + xen_state.xen_inf.virt_base),
> +		(unsigned) size);

This should be printed only if !xen_state.xen_inf.unmapped_initrd.
Why do not use xen_state.next_start.mod_start here?

Daniel
Jürgen Groß Feb. 25, 2016, 3:33 p.m. UTC | #2
On 25/02/16 13:47, Daniel Kiper wrote:
> On Thu, Feb 25, 2016 at 12:33:35PM +0100, Juergen Gross wrote:
>> Modern pvops linux kernels support an initrd not covered by the initial
>> mapping. This capability is flagged by an elf-note.
>>
>> In case the elf-note is set by the kernel don't place the initrd into
>> the initial mapping. This will allow to load larger initrds and/or
>> support domains with larger memory, as the initial mapping is limited
>> to 2GB and it is containing the p2m list.
>>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>> ---
>> V5: let call grub_xen_alloc_final() all subfunctions unconditionally
>>     and let them decide whether they need to do anything
>> V4: rename grub_xen_alloc_end() to grub_xen_alloc_final()
>> ---
>>  grub-core/loader/i386/xen.c        | 65 ++++++++++++++++++++++++++++++--------
>>  grub-core/loader/i386/xen_fileXX.c |  3 ++
>>  include/grub/xen_file.h            |  1 +
>>  3 files changed, 56 insertions(+), 13 deletions(-)
>>
>> diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
>> index 2e12763..466f0c0 100644
>> --- a/grub-core/loader/i386/xen.c
>> +++ b/grub-core/loader/i386/xen.c
>> @@ -228,6 +228,9 @@ grub_xen_p2m_alloc (void)
>>    grub_size_t p2msize;
>>    grub_err_t err;
>>
>> +  if (xen_state.virt_mfn_list)
>> +    return GRUB_ERR_NONE;
>> +
>>    xen_state.state.mfn_list = xen_state.max_addr;
>>    xen_state.next_start.mfn_list =
>>      xen_state.max_addr + xen_state.xen_inf.virt_base;
>> @@ -250,6 +253,9 @@ grub_xen_special_alloc (void)
>>    grub_relocator_chunk_t ch;
>>    grub_err_t err;
>>
>> +  if (xen_state.virt_start_info)
>> +    return GRUB_ERR_NONE;
>> +
>>    err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch,
>>  					 xen_state.max_addr,
>>  					 sizeof (xen_state.next_start));
>> @@ -281,6 +287,9 @@ grub_xen_pt_alloc (void)
>>    grub_uint64_t nr_info_pages;
>>    grub_uint64_t nr_pages, nr_pt_pages, nr_need_pages;
>>
>> +  if (xen_state.virt_pgtable)
>> +    return GRUB_ERR_NONE;
>> +
>>    xen_state.next_start.pt_base =
>>      xen_state.max_addr + xen_state.xen_inf.virt_base;
>>    xen_state.state.paging_start = xen_state.max_addr >> PAGE_SHIFT;
>> @@ -320,6 +329,24 @@ grub_xen_pt_alloc (void)
>>  }
>>
>>  static grub_err_t
>> +grub_xen_alloc_final (void)
>> +{
>> +  grub_err_t err;
>> +
>> +  err = grub_xen_p2m_alloc ();
>> +  if (err)
>> +    return err;
>> +  err = grub_xen_special_alloc ();
>> +  if (err)
>> +    return err;
>> +  err = grub_xen_pt_alloc ();
>> +  if (err)
>> +    return err;
> 
> Could you move grub_xen_p2m_alloc() here? This way grub_xen_alloc_final()
> will be real final in patch 11 and you do not need an extra condition
> around grub_xen_p2m_alloc().

No. Page tables must be allocated after p2m unless p2m is outside of
initial kernel mapping (patch 11).

> 
>> +
>> +  return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>>  grub_xen_boot (void)
>>  {
>>    grub_err_t err;
>> @@ -330,13 +357,7 @@ grub_xen_boot (void)
>>    if (grub_xen_n_allocated_shared_pages)
>>      return grub_error (GRUB_ERR_BUG, "active grants");
>>
>> -  err = grub_xen_p2m_alloc ();
>> -  if (err)
>> -    return err;
>> -  err = grub_xen_special_alloc ();
>> -  if (err)
>> -    return err;
>> -  err = grub_xen_pt_alloc ();
>> +  err = grub_xen_alloc_final ();
> 
> if (!xen_state.xen_inf.unmapped_initrd)
>   {
>     err = grub_xen_alloc_final ();
>     if (err)
>       goto fail;
>   }
> 
> This way you avoid checks in grub_xen_p2m_alloc(),
> grub_xen_special_alloc() and grub_xen_pt_alloc().

No. In case there is no initrd, but the kernel does support an unmapped
initrd, I would omit allocating special pages, p2m and page tables.

> 
>>    if (err)
>>      return err;
>>
>> @@ -610,6 +631,13 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
>>        goto fail;
>>      }
>>
>> +  if (xen_state.xen_inf.unmapped_initrd)
>> +    {
>> +      err = grub_xen_alloc_final ();
>> +      if (err)
>> +	goto fail;
>> +    }
>> +
>>    if (grub_initrd_init (argc, argv, &initrd_ctx))
>>      goto fail;
>>
>> @@ -627,14 +655,24 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
>>  	goto fail;
>>      }
>>
>> -  xen_state.next_start.mod_start =
>> -    xen_state.max_addr + xen_state.xen_inf.virt_base;
>> -  xen_state.next_start.mod_len = size;
> 
> Leave "xen_state.next_start.mod_len = size;" as is here and...
> 
>> -
>> -  xen_state.max_addr = ALIGN_UP (xen_state.max_addr + size, PAGE_SIZE);
>> +  if (xen_state.xen_inf.unmapped_initrd)
>> +    {
>> +      xen_state.next_start.flags |= SIF_MOD_START_PFN;
>> +      xen_state.next_start.mod_start = xen_state.max_addr >> PAGE_SHIFT;
>> +      xen_state.next_start.mod_len = size;
> 
> ... do not add it here...
> 
>> +    }
>> +  else
>> +    {
>> +      xen_state.next_start.mod_start =
>> +	xen_state.max_addr + xen_state.xen_inf.virt_base;
>> +      xen_state.next_start.mod_len = size;
> 
> ... and here...
> 
>> +    }
> 
> ... and you do not need curly brackets then.

I still do, as in the "if" part I still have two statements.

> 
>>    grub_dprintf ("xen", "Initrd, addr=0x%x, size=0x%x\n",
>> -		(unsigned) xen_state.next_start.mod_start, (unsigned) size);
>> +		(unsigned) (xen_state.max_addr + xen_state.xen_inf.virt_base),
>> +		(unsigned) size);
> 
> This should be printed only if !xen_state.xen_inf.unmapped_initrd.

Really? Why? We still have an initrd.

> Why do not use xen_state.next_start.mod_start here?

It is the pfn in case of unmapped_initrd.


Juergen
Daniel Kiper Feb. 26, 2016, 2 p.m. UTC | #3
On Thu, Feb 25, 2016 at 04:33:46PM +0100, Juergen Gross wrote:
> On 25/02/16 13:47, Daniel Kiper wrote:
> > On Thu, Feb 25, 2016 at 12:33:35PM +0100, Juergen Gross wrote:
> >> Modern pvops linux kernels support an initrd not covered by the initial
> >> mapping. This capability is flagged by an elf-note.
> >>
> >> In case the elf-note is set by the kernel don't place the initrd into
> >> the initial mapping. This will allow to load larger initrds and/or
> >> support domains with larger memory, as the initial mapping is limited
> >> to 2GB and it is containing the p2m list.
> >>
> >> Signed-off-by: Juergen Gross <jgross@suse.com>
> >> ---
> >> V5: let call grub_xen_alloc_final() all subfunctions unconditionally
> >>     and let them decide whether they need to do anything
> >> V4: rename grub_xen_alloc_end() to grub_xen_alloc_final()
> >> ---
> >>  grub-core/loader/i386/xen.c        | 65 ++++++++++++++++++++++++++++++--------
> >>  grub-core/loader/i386/xen_fileXX.c |  3 ++
> >>  include/grub/xen_file.h            |  1 +
> >>  3 files changed, 56 insertions(+), 13 deletions(-)
> >>
> >> diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
> >> index 2e12763..466f0c0 100644
> >> --- a/grub-core/loader/i386/xen.c
> >> +++ b/grub-core/loader/i386/xen.c
> >> @@ -228,6 +228,9 @@ grub_xen_p2m_alloc (void)
> >>    grub_size_t p2msize;
> >>    grub_err_t err;
> >>
> >> +  if (xen_state.virt_mfn_list)
> >> +    return GRUB_ERR_NONE;
> >> +
> >>    xen_state.state.mfn_list = xen_state.max_addr;
> >>    xen_state.next_start.mfn_list =
> >>      xen_state.max_addr + xen_state.xen_inf.virt_base;
> >> @@ -250,6 +253,9 @@ grub_xen_special_alloc (void)
> >>    grub_relocator_chunk_t ch;
> >>    grub_err_t err;
> >>
> >> +  if (xen_state.virt_start_info)
> >> +    return GRUB_ERR_NONE;
> >> +
> >>    err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch,
> >>  					 xen_state.max_addr,
> >>  					 sizeof (xen_state.next_start));
> >> @@ -281,6 +287,9 @@ grub_xen_pt_alloc (void)
> >>    grub_uint64_t nr_info_pages;
> >>    grub_uint64_t nr_pages, nr_pt_pages, nr_need_pages;
> >>
> >> +  if (xen_state.virt_pgtable)
> >> +    return GRUB_ERR_NONE;
> >> +
> >>    xen_state.next_start.pt_base =
> >>      xen_state.max_addr + xen_state.xen_inf.virt_base;
> >>    xen_state.state.paging_start = xen_state.max_addr >> PAGE_SHIFT;
> >> @@ -320,6 +329,24 @@ grub_xen_pt_alloc (void)
> >>  }
> >>
> >>  static grub_err_t
> >> +grub_xen_alloc_final (void)
> >> +{
> >> +  grub_err_t err;
> >> +
> >> +  err = grub_xen_p2m_alloc ();
> >> +  if (err)
> >> +    return err;
> >> +  err = grub_xen_special_alloc ();
> >> +  if (err)
> >> +    return err;
> >> +  err = grub_xen_pt_alloc ();
> >> +  if (err)
> >> +    return err;
> >
> > Could you move grub_xen_p2m_alloc() here? This way grub_xen_alloc_final()
> > will be real final in patch 11 and you do not need an extra condition
> > around grub_xen_p2m_alloc().
>
> No. Page tables must be allocated after p2m unless p2m is outside of
> initial kernel mapping (patch 11).

OK, I was afraid of that. However, then grub_xen_alloc_final() is not final.
So, maybe it should be called grub_xen_alloc_boot_data() or something like that.

> >> +  return GRUB_ERR_NONE;
> >> +}
> >> +
> >> +static grub_err_t
> >>  grub_xen_boot (void)
> >>  {
> >>    grub_err_t err;
> >> @@ -330,13 +357,7 @@ grub_xen_boot (void)
> >>    if (grub_xen_n_allocated_shared_pages)
> >>      return grub_error (GRUB_ERR_BUG, "active grants");
> >>
> >> -  err = grub_xen_p2m_alloc ();
> >> -  if (err)
> >> -    return err;
> >> -  err = grub_xen_special_alloc ();
> >> -  if (err)
> >> -    return err;
> >> -  err = grub_xen_pt_alloc ();
> >> +  err = grub_xen_alloc_final ();
> >
> > if (!xen_state.xen_inf.unmapped_initrd)
> >   {
> >     err = grub_xen_alloc_final ();
> >     if (err)
> >       goto fail;
> >   }
> >
> > This way you avoid checks in grub_xen_p2m_alloc(),
> > grub_xen_special_alloc() and grub_xen_pt_alloc().
>
> No. In case there is no initrd, but the kernel does support an unmapped
> initrd, I would omit allocating special pages, p2m and page tables.

Ups... I have missed that.

> >>    if (err)
> >>      return err;
> >>
> >> @@ -610,6 +631,13 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
> >>        goto fail;
> >>      }
> >>
> >> +  if (xen_state.xen_inf.unmapped_initrd)
> >> +    {
> >> +      err = grub_xen_alloc_final ();
> >> +      if (err)
> >> +	goto fail;
> >> +    }
> >> +
> >>    if (grub_initrd_init (argc, argv, &initrd_ctx))
> >>      goto fail;
> >>
> >> @@ -627,14 +655,24 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
> >>  	goto fail;
> >>      }
> >>
> >> -  xen_state.next_start.mod_start =
> >> -    xen_state.max_addr + xen_state.xen_inf.virt_base;
> >> -  xen_state.next_start.mod_len = size;
> >
> > Leave "xen_state.next_start.mod_len = size;" as is here and...
> >
> >> -
> >> -  xen_state.max_addr = ALIGN_UP (xen_state.max_addr + size, PAGE_SIZE);
> >> +  if (xen_state.xen_inf.unmapped_initrd)
> >> +    {
> >> +      xen_state.next_start.flags |= SIF_MOD_START_PFN;
> >> +      xen_state.next_start.mod_start = xen_state.max_addr >> PAGE_SHIFT;
> >> +      xen_state.next_start.mod_len = size;
> >
> > ... do not add it here...
> >
> >> +    }
> >> +  else
> >> +    {
> >> +      xen_state.next_start.mod_start =
> >> +	xen_state.max_addr + xen_state.xen_inf.virt_base;
> >> +      xen_state.next_start.mod_len = size;
> >
> > ... and here...
> >
> >> +    }
> >
> > ... and you do not need curly brackets then.
>
> I still do, as in the "if" part I still have two statements.

Yep, but else stuff does not need one.

> >>    grub_dprintf ("xen", "Initrd, addr=0x%x, size=0x%x\n",
> >> -		(unsigned) xen_state.next_start.mod_start, (unsigned) size);
> >> +		(unsigned) (xen_state.max_addr + xen_state.xen_inf.virt_base),
> >> +		(unsigned) size);
> >
> > This should be printed only if !xen_state.xen_inf.unmapped_initrd.
>
> Really? Why? We still have an initrd.
>
> > Why do not use xen_state.next_start.mod_start here?
>
> It is the pfn in case of unmapped_initrd.

Errr... I have looked at wrong line. Sorry about that.

Daniel
Jürgen Groß Feb. 26, 2016, 2:28 p.m. UTC | #4
On 26/02/16 15:00, Daniel Kiper wrote:
> On Thu, Feb 25, 2016 at 04:33:46PM +0100, Juergen Gross wrote:
>> On 25/02/16 13:47, Daniel Kiper wrote:
>>> On Thu, Feb 25, 2016 at 12:33:35PM +0100, Juergen Gross wrote:
>>>> Modern pvops linux kernels support an initrd not covered by the initial
>>>> mapping. This capability is flagged by an elf-note.
>>>>
>>>> In case the elf-note is set by the kernel don't place the initrd into
>>>> the initial mapping. This will allow to load larger initrds and/or
>>>> support domains with larger memory, as the initial mapping is limited
>>>> to 2GB and it is containing the p2m list.
>>>>
>>>> Signed-off-by: Juergen Gross <jgross@suse.com>
>>>> ---
>>>> V5: let call grub_xen_alloc_final() all subfunctions unconditionally
>>>>     and let them decide whether they need to do anything
>>>> V4: rename grub_xen_alloc_end() to grub_xen_alloc_final()
>>>> ---
>>>>  grub-core/loader/i386/xen.c        | 65 ++++++++++++++++++++++++++++++--------
>>>>  grub-core/loader/i386/xen_fileXX.c |  3 ++
>>>>  include/grub/xen_file.h            |  1 +
>>>>  3 files changed, 56 insertions(+), 13 deletions(-)
>>>>
>>>> diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
>>>> index 2e12763..466f0c0 100644
>>>> --- a/grub-core/loader/i386/xen.c
>>>> +++ b/grub-core/loader/i386/xen.c
>>>> @@ -228,6 +228,9 @@ grub_xen_p2m_alloc (void)
>>>>    grub_size_t p2msize;
>>>>    grub_err_t err;
>>>>
>>>> +  if (xen_state.virt_mfn_list)
>>>> +    return GRUB_ERR_NONE;
>>>> +
>>>>    xen_state.state.mfn_list = xen_state.max_addr;
>>>>    xen_state.next_start.mfn_list =
>>>>      xen_state.max_addr + xen_state.xen_inf.virt_base;
>>>> @@ -250,6 +253,9 @@ grub_xen_special_alloc (void)
>>>>    grub_relocator_chunk_t ch;
>>>>    grub_err_t err;
>>>>
>>>> +  if (xen_state.virt_start_info)
>>>> +    return GRUB_ERR_NONE;
>>>> +
>>>>    err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch,
>>>>  					 xen_state.max_addr,
>>>>  					 sizeof (xen_state.next_start));
>>>> @@ -281,6 +287,9 @@ grub_xen_pt_alloc (void)
>>>>    grub_uint64_t nr_info_pages;
>>>>    grub_uint64_t nr_pages, nr_pt_pages, nr_need_pages;
>>>>
>>>> +  if (xen_state.virt_pgtable)
>>>> +    return GRUB_ERR_NONE;
>>>> +
>>>>    xen_state.next_start.pt_base =
>>>>      xen_state.max_addr + xen_state.xen_inf.virt_base;
>>>>    xen_state.state.paging_start = xen_state.max_addr >> PAGE_SHIFT;
>>>> @@ -320,6 +329,24 @@ grub_xen_pt_alloc (void)
>>>>  }
>>>>
>>>>  static grub_err_t
>>>> +grub_xen_alloc_final (void)
>>>> +{
>>>> +  grub_err_t err;
>>>> +
>>>> +  err = grub_xen_p2m_alloc ();
>>>> +  if (err)
>>>> +    return err;
>>>> +  err = grub_xen_special_alloc ();
>>>> +  if (err)
>>>> +    return err;
>>>> +  err = grub_xen_pt_alloc ();
>>>> +  if (err)
>>>> +    return err;
>>>
>>> Could you move grub_xen_p2m_alloc() here? This way grub_xen_alloc_final()
>>> will be real final in patch 11 and you do not need an extra condition
>>> around grub_xen_p2m_alloc().
>>
>> No. Page tables must be allocated after p2m unless p2m is outside of
>> initial kernel mapping (patch 11).
> 
> OK, I was afraid of that. However, then grub_xen_alloc_final() is not final.

Sure it is. Patch 11 just adds allocation to grub_xen_alloc_final(), not
after it.

> So, maybe it should be called grub_xen_alloc_boot_data() or something like that.
> 
>>>> +  return GRUB_ERR_NONE;
>>>> +}
>>>> +
>>>> +static grub_err_t
>>>>  grub_xen_boot (void)
>>>>  {
>>>>    grub_err_t err;
>>>> @@ -330,13 +357,7 @@ grub_xen_boot (void)
>>>>    if (grub_xen_n_allocated_shared_pages)
>>>>      return grub_error (GRUB_ERR_BUG, "active grants");
>>>>
>>>> -  err = grub_xen_p2m_alloc ();
>>>> -  if (err)
>>>> -    return err;
>>>> -  err = grub_xen_special_alloc ();
>>>> -  if (err)
>>>> -    return err;
>>>> -  err = grub_xen_pt_alloc ();
>>>> +  err = grub_xen_alloc_final ();
>>>
>>> if (!xen_state.xen_inf.unmapped_initrd)
>>>   {
>>>     err = grub_xen_alloc_final ();
>>>     if (err)
>>>       goto fail;
>>>   }
>>>
>>> This way you avoid checks in grub_xen_p2m_alloc(),
>>> grub_xen_special_alloc() and grub_xen_pt_alloc().
>>
>> No. In case there is no initrd, but the kernel does support an unmapped
>> initrd, I would omit allocating special pages, p2m and page tables.
> 
> Ups... I have missed that.
> 
>>>>    if (err)
>>>>      return err;
>>>>
>>>> @@ -610,6 +631,13 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
>>>>        goto fail;
>>>>      }
>>>>
>>>> +  if (xen_state.xen_inf.unmapped_initrd)
>>>> +    {
>>>> +      err = grub_xen_alloc_final ();
>>>> +      if (err)
>>>> +	goto fail;
>>>> +    }
>>>> +
>>>>    if (grub_initrd_init (argc, argv, &initrd_ctx))
>>>>      goto fail;
>>>>
>>>> @@ -627,14 +655,24 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
>>>>  	goto fail;
>>>>      }
>>>>
>>>> -  xen_state.next_start.mod_start =
>>>> -    xen_state.max_addr + xen_state.xen_inf.virt_base;
>>>> -  xen_state.next_start.mod_len = size;
>>>
>>> Leave "xen_state.next_start.mod_len = size;" as is here and...
>>>
>>>> -
>>>> -  xen_state.max_addr = ALIGN_UP (xen_state.max_addr + size, PAGE_SIZE);
>>>> +  if (xen_state.xen_inf.unmapped_initrd)
>>>> +    {
>>>> +      xen_state.next_start.flags |= SIF_MOD_START_PFN;
>>>> +      xen_state.next_start.mod_start = xen_state.max_addr >> PAGE_SHIFT;
>>>> +      xen_state.next_start.mod_len = size;
>>>
>>> ... do not add it here...
>>>
>>>> +    }
>>>> +  else
>>>> +    {
>>>> +      xen_state.next_start.mod_start =
>>>> +	xen_state.max_addr + xen_state.xen_inf.virt_base;
>>>> +      xen_state.next_start.mod_len = size;
>>>
>>> ... and here...
>>>
>>>> +    }
>>>
>>> ... and you do not need curly brackets then.
>>
>> I still do, as in the "if" part I still have two statements.
> 
> Yep, but else stuff does not need one.

Ah, okay. Too many different coding styles. Linux kernel would keep
the braces.

> 
>>>>    grub_dprintf ("xen", "Initrd, addr=0x%x, size=0x%x\n",
>>>> -		(unsigned) xen_state.next_start.mod_start, (unsigned) size);
>>>> +		(unsigned) (xen_state.max_addr + xen_state.xen_inf.virt_base),
>>>> +		(unsigned) size);
>>>
>>> This should be printed only if !xen_state.xen_inf.unmapped_initrd.
>>
>> Really? Why? We still have an initrd.
>>
>>> Why do not use xen_state.next_start.mod_start here?
>>
>> It is the pfn in case of unmapped_initrd.
> 
> Errr... I have looked at wrong line. Sorry about that.

NP.


Juergen
Daniel Kiper Feb. 26, 2016, 3:41 p.m. UTC | #5
On Fri, Feb 26, 2016 at 03:28:21PM +0100, Juergen Gross wrote:
> On 26/02/16 15:00, Daniel Kiper wrote:
> > On Thu, Feb 25, 2016 at 04:33:46PM +0100, Juergen Gross wrote:
> >> On 25/02/16 13:47, Daniel Kiper wrote:
> >>> On Thu, Feb 25, 2016 at 12:33:35PM +0100, Juergen Gross wrote:
> >>>> Modern pvops linux kernels support an initrd not covered by the initial
> >>>> mapping. This capability is flagged by an elf-note.
> >>>>
> >>>> In case the elf-note is set by the kernel don't place the initrd into
> >>>> the initial mapping. This will allow to load larger initrds and/or
> >>>> support domains with larger memory, as the initial mapping is limited
> >>>> to 2GB and it is containing the p2m list.
> >>>>
> >>>> Signed-off-by: Juergen Gross <jgross@suse.com>
> >>>> ---
> >>>> V5: let call grub_xen_alloc_final() all subfunctions unconditionally
> >>>>     and let them decide whether they need to do anything
> >>>> V4: rename grub_xen_alloc_end() to grub_xen_alloc_final()
> >>>> ---
> >>>>  grub-core/loader/i386/xen.c        | 65 ++++++++++++++++++++++++++++++--------
> >>>>  grub-core/loader/i386/xen_fileXX.c |  3 ++
> >>>>  include/grub/xen_file.h            |  1 +
> >>>>  3 files changed, 56 insertions(+), 13 deletions(-)
> >>>>
> >>>> diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
> >>>> index 2e12763..466f0c0 100644
> >>>> --- a/grub-core/loader/i386/xen.c
> >>>> +++ b/grub-core/loader/i386/xen.c
> >>>> @@ -228,6 +228,9 @@ grub_xen_p2m_alloc (void)
> >>>>    grub_size_t p2msize;
> >>>>    grub_err_t err;
> >>>>
> >>>> +  if (xen_state.virt_mfn_list)
> >>>> +    return GRUB_ERR_NONE;
> >>>> +
> >>>>    xen_state.state.mfn_list = xen_state.max_addr;
> >>>>    xen_state.next_start.mfn_list =
> >>>>      xen_state.max_addr + xen_state.xen_inf.virt_base;
> >>>> @@ -250,6 +253,9 @@ grub_xen_special_alloc (void)
> >>>>    grub_relocator_chunk_t ch;
> >>>>    grub_err_t err;
> >>>>
> >>>> +  if (xen_state.virt_start_info)
> >>>> +    return GRUB_ERR_NONE;
> >>>> +
> >>>>    err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch,
> >>>>  					 xen_state.max_addr,
> >>>>  					 sizeof (xen_state.next_start));
> >>>> @@ -281,6 +287,9 @@ grub_xen_pt_alloc (void)
> >>>>    grub_uint64_t nr_info_pages;
> >>>>    grub_uint64_t nr_pages, nr_pt_pages, nr_need_pages;
> >>>>
> >>>> +  if (xen_state.virt_pgtable)
> >>>> +    return GRUB_ERR_NONE;
> >>>> +
> >>>>    xen_state.next_start.pt_base =
> >>>>      xen_state.max_addr + xen_state.xen_inf.virt_base;
> >>>>    xen_state.state.paging_start = xen_state.max_addr >> PAGE_SHIFT;
> >>>> @@ -320,6 +329,24 @@ grub_xen_pt_alloc (void)
> >>>>  }
> >>>>
> >>>>  static grub_err_t
> >>>> +grub_xen_alloc_final (void)
> >>>> +{
> >>>> +  grub_err_t err;
> >>>> +
> >>>> +  err = grub_xen_p2m_alloc ();
> >>>> +  if (err)
> >>>> +    return err;
> >>>> +  err = grub_xen_special_alloc ();
> >>>> +  if (err)
> >>>> +    return err;
> >>>> +  err = grub_xen_pt_alloc ();
> >>>> +  if (err)
> >>>> +    return err;
> >>>
> >>> Could you move grub_xen_p2m_alloc() here? This way grub_xen_alloc_final()
> >>> will be real final in patch 11 and you do not need an extra condition
> >>> around grub_xen_p2m_alloc().
> >>
> >> No. Page tables must be allocated after p2m unless p2m is outside of
> >> initial kernel mapping (patch 11).
> >
> > OK, I was afraid of that. However, then grub_xen_alloc_final() is not final.
>
> Sure it is. Patch 11 just adds allocation to grub_xen_alloc_final(), not
> after it.

Excerpt from patch 11:

@@ -474,6 +503,12 @@ grub_xen_boot (void)
   err = grub_xen_alloc_final ();
   if (err)
     return err;
+  if (xen_state.xen_inf.has_p2m_base)
+    {
+      err = grub_xen_p2m_alloc ();
+      if (err)
+        return err;
+    }

> > So, maybe it should be called grub_xen_alloc_boot_data() or something like that.

Then my previous comment is still valid.

Daniel
Jürgen Groß Feb. 29, 2016, 8:27 a.m. UTC | #6
On 26/02/16 16:41, Daniel Kiper wrote:
> On Fri, Feb 26, 2016 at 03:28:21PM +0100, Juergen Gross wrote:
>> On 26/02/16 15:00, Daniel Kiper wrote:
>>> On Thu, Feb 25, 2016 at 04:33:46PM +0100, Juergen Gross wrote:
>>>> On 25/02/16 13:47, Daniel Kiper wrote:
>>>>> On Thu, Feb 25, 2016 at 12:33:35PM +0100, Juergen Gross wrote:
>>>>>> Modern pvops linux kernels support an initrd not covered by the initial
>>>>>> mapping. This capability is flagged by an elf-note.
>>>>>>
>>>>>> In case the elf-note is set by the kernel don't place the initrd into
>>>>>> the initial mapping. This will allow to load larger initrds and/or
>>>>>> support domains with larger memory, as the initial mapping is limited
>>>>>> to 2GB and it is containing the p2m list.
>>>>>>
>>>>>> Signed-off-by: Juergen Gross <jgross@suse.com>
>>>>>> ---
>>>>>> V5: let call grub_xen_alloc_final() all subfunctions unconditionally
>>>>>>     and let them decide whether they need to do anything
>>>>>> V4: rename grub_xen_alloc_end() to grub_xen_alloc_final()
>>>>>> ---
>>>>>>  grub-core/loader/i386/xen.c        | 65 ++++++++++++++++++++++++++++++--------
>>>>>>  grub-core/loader/i386/xen_fileXX.c |  3 ++
>>>>>>  include/grub/xen_file.h            |  1 +
>>>>>>  3 files changed, 56 insertions(+), 13 deletions(-)
>>>>>>
>>>>>> diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
>>>>>> index 2e12763..466f0c0 100644
>>>>>> --- a/grub-core/loader/i386/xen.c
>>>>>> +++ b/grub-core/loader/i386/xen.c
>>>>>> @@ -228,6 +228,9 @@ grub_xen_p2m_alloc (void)
>>>>>>    grub_size_t p2msize;
>>>>>>    grub_err_t err;
>>>>>>
>>>>>> +  if (xen_state.virt_mfn_list)
>>>>>> +    return GRUB_ERR_NONE;
>>>>>> +
>>>>>>    xen_state.state.mfn_list = xen_state.max_addr;
>>>>>>    xen_state.next_start.mfn_list =
>>>>>>      xen_state.max_addr + xen_state.xen_inf.virt_base;
>>>>>> @@ -250,6 +253,9 @@ grub_xen_special_alloc (void)
>>>>>>    grub_relocator_chunk_t ch;
>>>>>>    grub_err_t err;
>>>>>>
>>>>>> +  if (xen_state.virt_start_info)
>>>>>> +    return GRUB_ERR_NONE;
>>>>>> +
>>>>>>    err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch,
>>>>>>  					 xen_state.max_addr,
>>>>>>  					 sizeof (xen_state.next_start));
>>>>>> @@ -281,6 +287,9 @@ grub_xen_pt_alloc (void)
>>>>>>    grub_uint64_t nr_info_pages;
>>>>>>    grub_uint64_t nr_pages, nr_pt_pages, nr_need_pages;
>>>>>>
>>>>>> +  if (xen_state.virt_pgtable)
>>>>>> +    return GRUB_ERR_NONE;
>>>>>> +
>>>>>>    xen_state.next_start.pt_base =
>>>>>>      xen_state.max_addr + xen_state.xen_inf.virt_base;
>>>>>>    xen_state.state.paging_start = xen_state.max_addr >> PAGE_SHIFT;
>>>>>> @@ -320,6 +329,24 @@ grub_xen_pt_alloc (void)
>>>>>>  }
>>>>>>
>>>>>>  static grub_err_t
>>>>>> +grub_xen_alloc_final (void)
>>>>>> +{
>>>>>> +  grub_err_t err;
>>>>>> +
>>>>>> +  err = grub_xen_p2m_alloc ();
>>>>>> +  if (err)
>>>>>> +    return err;
>>>>>> +  err = grub_xen_special_alloc ();
>>>>>> +  if (err)
>>>>>> +    return err;
>>>>>> +  err = grub_xen_pt_alloc ();
>>>>>> +  if (err)
>>>>>> +    return err;
>>>>>
>>>>> Could you move grub_xen_p2m_alloc() here? This way grub_xen_alloc_final()
>>>>> will be real final in patch 11 and you do not need an extra condition
>>>>> around grub_xen_p2m_alloc().
>>>>
>>>> No. Page tables must be allocated after p2m unless p2m is outside of
>>>> initial kernel mapping (patch 11).
>>>
>>> OK, I was afraid of that. However, then grub_xen_alloc_final() is not final.
>>
>> Sure it is. Patch 11 just adds allocation to grub_xen_alloc_final(), not
>> after it.
> 
> Excerpt from patch 11:
> 
> @@ -474,6 +503,12 @@ grub_xen_boot (void)
>    err = grub_xen_alloc_final ();
>    if (err)
>      return err;
> +  if (xen_state.xen_inf.has_p2m_base)
> +    {
> +      err = grub_xen_p2m_alloc ();
> +      if (err)
> +        return err;
> +    }
> 

Hmph. No idea what I looked at when writing my previous reply.

>>> So, maybe it should be called grub_xen_alloc_boot_data() or something like that.
> 
> Then my previous comment is still valid.

What about naming it grub_xen_alloc_kernel_mapping() ? This is what it
really does: It is allocating all not yet allocated areas which are to
be included in the initial kernel mapping.

Juergen
Daniel Kiper Feb. 29, 2016, 3:43 p.m. UTC | #7
On Mon, Feb 29, 2016 at 09:27:42AM +0100, Juergen Gross wrote:
> On 26/02/16 16:41, Daniel Kiper wrote:
> > On Fri, Feb 26, 2016 at 03:28:21PM +0100, Juergen Gross wrote:
> >> On 26/02/16 15:00, Daniel Kiper wrote:
> >>> On Thu, Feb 25, 2016 at 04:33:46PM +0100, Juergen Gross wrote:
> >>>> On 25/02/16 13:47, Daniel Kiper wrote:
> >>>>> On Thu, Feb 25, 2016 at 12:33:35PM +0100, Juergen Gross wrote:
> >>>>>> Modern pvops linux kernels support an initrd not covered by the initial
> >>>>>> mapping. This capability is flagged by an elf-note.
> >>>>>>
> >>>>>> In case the elf-note is set by the kernel don't place the initrd into
> >>>>>> the initial mapping. This will allow to load larger initrds and/or
> >>>>>> support domains with larger memory, as the initial mapping is limited
> >>>>>> to 2GB and it is containing the p2m list.
> >>>>>>
> >>>>>> Signed-off-by: Juergen Gross <jgross@suse.com>
> >>>>>> ---
> >>>>>> V5: let call grub_xen_alloc_final() all subfunctions unconditionally
> >>>>>>     and let them decide whether they need to do anything
> >>>>>> V4: rename grub_xen_alloc_end() to grub_xen_alloc_final()
> >>>>>> ---
> >>>>>>  grub-core/loader/i386/xen.c        | 65 ++++++++++++++++++++++++++++++--------
> >>>>>>  grub-core/loader/i386/xen_fileXX.c |  3 ++
> >>>>>>  include/grub/xen_file.h            |  1 +
> >>>>>>  3 files changed, 56 insertions(+), 13 deletions(-)
> >>>>>>
> >>>>>> diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
> >>>>>> index 2e12763..466f0c0 100644
> >>>>>> --- a/grub-core/loader/i386/xen.c
> >>>>>> +++ b/grub-core/loader/i386/xen.c
> >>>>>> @@ -228,6 +228,9 @@ grub_xen_p2m_alloc (void)
> >>>>>>    grub_size_t p2msize;
> >>>>>>    grub_err_t err;
> >>>>>>
> >>>>>> +  if (xen_state.virt_mfn_list)
> >>>>>> +    return GRUB_ERR_NONE;
> >>>>>> +
> >>>>>>    xen_state.state.mfn_list = xen_state.max_addr;
> >>>>>>    xen_state.next_start.mfn_list =
> >>>>>>      xen_state.max_addr + xen_state.xen_inf.virt_base;
> >>>>>> @@ -250,6 +253,9 @@ grub_xen_special_alloc (void)
> >>>>>>    grub_relocator_chunk_t ch;
> >>>>>>    grub_err_t err;
> >>>>>>
> >>>>>> +  if (xen_state.virt_start_info)
> >>>>>> +    return GRUB_ERR_NONE;
> >>>>>> +
> >>>>>>    err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch,
> >>>>>>  					 xen_state.max_addr,
> >>>>>>  					 sizeof (xen_state.next_start));
> >>>>>> @@ -281,6 +287,9 @@ grub_xen_pt_alloc (void)
> >>>>>>    grub_uint64_t nr_info_pages;
> >>>>>>    grub_uint64_t nr_pages, nr_pt_pages, nr_need_pages;
> >>>>>>
> >>>>>> +  if (xen_state.virt_pgtable)
> >>>>>> +    return GRUB_ERR_NONE;
> >>>>>> +
> >>>>>>    xen_state.next_start.pt_base =
> >>>>>>      xen_state.max_addr + xen_state.xen_inf.virt_base;
> >>>>>>    xen_state.state.paging_start = xen_state.max_addr >> PAGE_SHIFT;
> >>>>>> @@ -320,6 +329,24 @@ grub_xen_pt_alloc (void)
> >>>>>>  }
> >>>>>>
> >>>>>>  static grub_err_t
> >>>>>> +grub_xen_alloc_final (void)
> >>>>>> +{
> >>>>>> +  grub_err_t err;
> >>>>>> +
> >>>>>> +  err = grub_xen_p2m_alloc ();
> >>>>>> +  if (err)
> >>>>>> +    return err;
> >>>>>> +  err = grub_xen_special_alloc ();
> >>>>>> +  if (err)
> >>>>>> +    return err;
> >>>>>> +  err = grub_xen_pt_alloc ();
> >>>>>> +  if (err)
> >>>>>> +    return err;
> >>>>>
> >>>>> Could you move grub_xen_p2m_alloc() here? This way grub_xen_alloc_final()
> >>>>> will be real final in patch 11 and you do not need an extra condition
> >>>>> around grub_xen_p2m_alloc().
> >>>>
> >>>> No. Page tables must be allocated after p2m unless p2m is outside of
> >>>> initial kernel mapping (patch 11).
> >>>
> >>> OK, I was afraid of that. However, then grub_xen_alloc_final() is not final.
> >>
> >> Sure it is. Patch 11 just adds allocation to grub_xen_alloc_final(), not
> >> after it.
> >
> > Excerpt from patch 11:
> >
> > @@ -474,6 +503,12 @@ grub_xen_boot (void)
> >    err = grub_xen_alloc_final ();
> >    if (err)
> >      return err;
> > +  if (xen_state.xen_inf.has_p2m_base)
> > +    {
> > +      err = grub_xen_p2m_alloc ();
> > +      if (err)
> > +        return err;
> > +    }
> >
>
> Hmph. No idea what I looked at when writing my previous reply.
>
> >>> So, maybe it should be called grub_xen_alloc_boot_data() or something like that.
> >
> > Then my previous comment is still valid.
>
> What about naming it grub_xen_alloc_kernel_mapping() ? This is what it
> really does: It is allocating all not yet allocated areas which are to
> be included in the initial kernel mapping.

This function does three things:
  - allocate memory for p2m array,
  - allocate special pages (e.g. console),
  - allocate memory for page tables.

Three of them are part of boot data described by struct start_info.
Well, there are also other required stuff to properly boot PV guest.
So, I can agree that grub_xen_alloc_boot_data() is not perfect but
I cannot find anything better. Additionally, IMO grub_xen_alloc_kernel_mapping()
is not right choice too. It suggests that this functions does anything
with kernel mapping. Yep, it does, however, this is only one third
of this function. So, I tend to use my proposal or anything better
which is short and quite well describes what is going in this
function as whole.

Daniel
Jürgen Groß Feb. 29, 2016, 3:49 p.m. UTC | #8
On 29/02/16 16:43, Daniel Kiper wrote:
> On Mon, Feb 29, 2016 at 09:27:42AM +0100, Juergen Gross wrote:
>> On 26/02/16 16:41, Daniel Kiper wrote:
>>> On Fri, Feb 26, 2016 at 03:28:21PM +0100, Juergen Gross wrote:
>>>> On 26/02/16 15:00, Daniel Kiper wrote:
>>>>> On Thu, Feb 25, 2016 at 04:33:46PM +0100, Juergen Gross wrote:
>>>>>> On 25/02/16 13:47, Daniel Kiper wrote:
>>>>>>> On Thu, Feb 25, 2016 at 12:33:35PM +0100, Juergen Gross wrote:
>>>>>>>> Modern pvops linux kernels support an initrd not covered by the initial
>>>>>>>> mapping. This capability is flagged by an elf-note.
>>>>>>>>
>>>>>>>> In case the elf-note is set by the kernel don't place the initrd into
>>>>>>>> the initial mapping. This will allow to load larger initrds and/or
>>>>>>>> support domains with larger memory, as the initial mapping is limited
>>>>>>>> to 2GB and it is containing the p2m list.
>>>>>>>>
>>>>>>>> Signed-off-by: Juergen Gross <jgross@suse.com>
>>>>>>>> ---
>>>>>>>> V5: let call grub_xen_alloc_final() all subfunctions unconditionally
>>>>>>>>     and let them decide whether they need to do anything
>>>>>>>> V4: rename grub_xen_alloc_end() to grub_xen_alloc_final()
>>>>>>>> ---
>>>>>>>>  grub-core/loader/i386/xen.c        | 65 ++++++++++++++++++++++++++++++--------
>>>>>>>>  grub-core/loader/i386/xen_fileXX.c |  3 ++
>>>>>>>>  include/grub/xen_file.h            |  1 +
>>>>>>>>  3 files changed, 56 insertions(+), 13 deletions(-)
>>>>>>>>
>>>>>>>> diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
>>>>>>>> index 2e12763..466f0c0 100644
>>>>>>>> --- a/grub-core/loader/i386/xen.c
>>>>>>>> +++ b/grub-core/loader/i386/xen.c
>>>>>>>> @@ -228,6 +228,9 @@ grub_xen_p2m_alloc (void)
>>>>>>>>    grub_size_t p2msize;
>>>>>>>>    grub_err_t err;
>>>>>>>>
>>>>>>>> +  if (xen_state.virt_mfn_list)
>>>>>>>> +    return GRUB_ERR_NONE;
>>>>>>>> +
>>>>>>>>    xen_state.state.mfn_list = xen_state.max_addr;
>>>>>>>>    xen_state.next_start.mfn_list =
>>>>>>>>      xen_state.max_addr + xen_state.xen_inf.virt_base;
>>>>>>>> @@ -250,6 +253,9 @@ grub_xen_special_alloc (void)
>>>>>>>>    grub_relocator_chunk_t ch;
>>>>>>>>    grub_err_t err;
>>>>>>>>
>>>>>>>> +  if (xen_state.virt_start_info)
>>>>>>>> +    return GRUB_ERR_NONE;
>>>>>>>> +
>>>>>>>>    err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch,
>>>>>>>>  					 xen_state.max_addr,
>>>>>>>>  					 sizeof (xen_state.next_start));
>>>>>>>> @@ -281,6 +287,9 @@ grub_xen_pt_alloc (void)
>>>>>>>>    grub_uint64_t nr_info_pages;
>>>>>>>>    grub_uint64_t nr_pages, nr_pt_pages, nr_need_pages;
>>>>>>>>
>>>>>>>> +  if (xen_state.virt_pgtable)
>>>>>>>> +    return GRUB_ERR_NONE;
>>>>>>>> +
>>>>>>>>    xen_state.next_start.pt_base =
>>>>>>>>      xen_state.max_addr + xen_state.xen_inf.virt_base;
>>>>>>>>    xen_state.state.paging_start = xen_state.max_addr >> PAGE_SHIFT;
>>>>>>>> @@ -320,6 +329,24 @@ grub_xen_pt_alloc (void)
>>>>>>>>  }
>>>>>>>>
>>>>>>>>  static grub_err_t
>>>>>>>> +grub_xen_alloc_final (void)
>>>>>>>> +{
>>>>>>>> +  grub_err_t err;
>>>>>>>> +
>>>>>>>> +  err = grub_xen_p2m_alloc ();
>>>>>>>> +  if (err)
>>>>>>>> +    return err;
>>>>>>>> +  err = grub_xen_special_alloc ();
>>>>>>>> +  if (err)
>>>>>>>> +    return err;
>>>>>>>> +  err = grub_xen_pt_alloc ();
>>>>>>>> +  if (err)
>>>>>>>> +    return err;
>>>>>>>
>>>>>>> Could you move grub_xen_p2m_alloc() here? This way grub_xen_alloc_final()
>>>>>>> will be real final in patch 11 and you do not need an extra condition
>>>>>>> around grub_xen_p2m_alloc().
>>>>>>
>>>>>> No. Page tables must be allocated after p2m unless p2m is outside of
>>>>>> initial kernel mapping (patch 11).
>>>>>
>>>>> OK, I was afraid of that. However, then grub_xen_alloc_final() is not final.
>>>>
>>>> Sure it is. Patch 11 just adds allocation to grub_xen_alloc_final(), not
>>>> after it.
>>>
>>> Excerpt from patch 11:
>>>
>>> @@ -474,6 +503,12 @@ grub_xen_boot (void)
>>>    err = grub_xen_alloc_final ();
>>>    if (err)
>>>      return err;
>>> +  if (xen_state.xen_inf.has_p2m_base)
>>> +    {
>>> +      err = grub_xen_p2m_alloc ();
>>> +      if (err)
>>> +        return err;
>>> +    }
>>>
>>
>> Hmph. No idea what I looked at when writing my previous reply.
>>
>>>>> So, maybe it should be called grub_xen_alloc_boot_data() or something like that.
>>>
>>> Then my previous comment is still valid.
>>
>> What about naming it grub_xen_alloc_kernel_mapping() ? This is what it
>> really does: It is allocating all not yet allocated areas which are to
>> be included in the initial kernel mapping.
> 
> This function does three things:
>   - allocate memory for p2m array,
>   - allocate special pages (e.g. console),
>   - allocate memory for page tables.
> 
> Three of them are part of boot data described by struct start_info.
> Well, there are also other required stuff to properly boot PV guest.
> So, I can agree that grub_xen_alloc_boot_data() is not perfect but
> I cannot find anything better. Additionally, IMO grub_xen_alloc_kernel_mapping()
> is not right choice too. It suggests that this functions does anything
> with kernel mapping. Yep, it does, however, this is only one third
> of this function. So, I tend to use my proposal or anything better
> which is short and quite well describes what is going in this
> function as whole.

Yeah. grub_xen_alloc_stuff() with a nice comment. ;-)

Okay, lets stick with grub_xen_alloc_boot_data() and add a comment
explaining that the function will allocate everything not yet allocated
and covered by the initial page tables.


Juergen
Daniel Kiper Feb. 29, 2016, 4:22 p.m. UTC | #9
On Mon, Feb 29, 2016 at 04:49:04PM +0100, Juergen Gross wrote:
> On 29/02/16 16:43, Daniel Kiper wrote:
> > On Mon, Feb 29, 2016 at 09:27:42AM +0100, Juergen Gross wrote:
> >> On 26/02/16 16:41, Daniel Kiper wrote:
> >>> On Fri, Feb 26, 2016 at 03:28:21PM +0100, Juergen Gross wrote:
> >>>> On 26/02/16 15:00, Daniel Kiper wrote:
> >>>>> On Thu, Feb 25, 2016 at 04:33:46PM +0100, Juergen Gross wrote:
> >>>>>> On 25/02/16 13:47, Daniel Kiper wrote:
> >>>>>>> On Thu, Feb 25, 2016 at 12:33:35PM +0100, Juergen Gross wrote:
> >>>>>>>> Modern pvops linux kernels support an initrd not covered by the initial
> >>>>>>>> mapping. This capability is flagged by an elf-note.
> >>>>>>>>
> >>>>>>>> In case the elf-note is set by the kernel don't place the initrd into
> >>>>>>>> the initial mapping. This will allow to load larger initrds and/or
> >>>>>>>> support domains with larger memory, as the initial mapping is limited
> >>>>>>>> to 2GB and it is containing the p2m list.
> >>>>>>>>
> >>>>>>>> Signed-off-by: Juergen Gross <jgross@suse.com>
> >>>>>>>> ---
> >>>>>>>> V5: let call grub_xen_alloc_final() all subfunctions unconditionally
> >>>>>>>>     and let them decide whether they need to do anything
> >>>>>>>> V4: rename grub_xen_alloc_end() to grub_xen_alloc_final()
> >>>>>>>> ---
> >>>>>>>>  grub-core/loader/i386/xen.c        | 65 ++++++++++++++++++++++++++++++--------
> >>>>>>>>  grub-core/loader/i386/xen_fileXX.c |  3 ++
> >>>>>>>>  include/grub/xen_file.h            |  1 +
> >>>>>>>>  3 files changed, 56 insertions(+), 13 deletions(-)
> >>>>>>>>
> >>>>>>>> diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
> >>>>>>>> index 2e12763..466f0c0 100644
> >>>>>>>> --- a/grub-core/loader/i386/xen.c
> >>>>>>>> +++ b/grub-core/loader/i386/xen.c
> >>>>>>>> @@ -228,6 +228,9 @@ grub_xen_p2m_alloc (void)
> >>>>>>>>    grub_size_t p2msize;
> >>>>>>>>    grub_err_t err;
> >>>>>>>>
> >>>>>>>> +  if (xen_state.virt_mfn_list)
> >>>>>>>> +    return GRUB_ERR_NONE;
> >>>>>>>> +
> >>>>>>>>    xen_state.state.mfn_list = xen_state.max_addr;
> >>>>>>>>    xen_state.next_start.mfn_list =
> >>>>>>>>      xen_state.max_addr + xen_state.xen_inf.virt_base;
> >>>>>>>> @@ -250,6 +253,9 @@ grub_xen_special_alloc (void)
> >>>>>>>>    grub_relocator_chunk_t ch;
> >>>>>>>>    grub_err_t err;
> >>>>>>>>
> >>>>>>>> +  if (xen_state.virt_start_info)
> >>>>>>>> +    return GRUB_ERR_NONE;
> >>>>>>>> +
> >>>>>>>>    err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch,
> >>>>>>>>  					 xen_state.max_addr,
> >>>>>>>>  					 sizeof (xen_state.next_start));
> >>>>>>>> @@ -281,6 +287,9 @@ grub_xen_pt_alloc (void)
> >>>>>>>>    grub_uint64_t nr_info_pages;
> >>>>>>>>    grub_uint64_t nr_pages, nr_pt_pages, nr_need_pages;
> >>>>>>>>
> >>>>>>>> +  if (xen_state.virt_pgtable)
> >>>>>>>> +    return GRUB_ERR_NONE;
> >>>>>>>> +
> >>>>>>>>    xen_state.next_start.pt_base =
> >>>>>>>>      xen_state.max_addr + xen_state.xen_inf.virt_base;
> >>>>>>>>    xen_state.state.paging_start = xen_state.max_addr >> PAGE_SHIFT;
> >>>>>>>> @@ -320,6 +329,24 @@ grub_xen_pt_alloc (void)
> >>>>>>>>  }
> >>>>>>>>
> >>>>>>>>  static grub_err_t
> >>>>>>>> +grub_xen_alloc_final (void)
> >>>>>>>> +{
> >>>>>>>> +  grub_err_t err;
> >>>>>>>> +
> >>>>>>>> +  err = grub_xen_p2m_alloc ();
> >>>>>>>> +  if (err)
> >>>>>>>> +    return err;
> >>>>>>>> +  err = grub_xen_special_alloc ();
> >>>>>>>> +  if (err)
> >>>>>>>> +    return err;
> >>>>>>>> +  err = grub_xen_pt_alloc ();
> >>>>>>>> +  if (err)
> >>>>>>>> +    return err;
> >>>>>>>
> >>>>>>> Could you move grub_xen_p2m_alloc() here? This way grub_xen_alloc_final()
> >>>>>>> will be real final in patch 11 and you do not need an extra condition
> >>>>>>> around grub_xen_p2m_alloc().
> >>>>>>
> >>>>>> No. Page tables must be allocated after p2m unless p2m is outside of
> >>>>>> initial kernel mapping (patch 11).
> >>>>>
> >>>>> OK, I was afraid of that. However, then grub_xen_alloc_final() is not final.
> >>>>
> >>>> Sure it is. Patch 11 just adds allocation to grub_xen_alloc_final(), not
> >>>> after it.
> >>>
> >>> Excerpt from patch 11:
> >>>
> >>> @@ -474,6 +503,12 @@ grub_xen_boot (void)
> >>>    err = grub_xen_alloc_final ();
> >>>    if (err)
> >>>      return err;
> >>> +  if (xen_state.xen_inf.has_p2m_base)
> >>> +    {
> >>> +      err = grub_xen_p2m_alloc ();
> >>> +      if (err)
> >>> +        return err;
> >>> +    }
> >>>
> >>
> >> Hmph. No idea what I looked at when writing my previous reply.
> >>
> >>>>> So, maybe it should be called grub_xen_alloc_boot_data() or something like that.
> >>>
> >>> Then my previous comment is still valid.
> >>
> >> What about naming it grub_xen_alloc_kernel_mapping() ? This is what it
> >> really does: It is allocating all not yet allocated areas which are to
> >> be included in the initial kernel mapping.
> >
> > This function does three things:
> >   - allocate memory for p2m array,
> >   - allocate special pages (e.g. console),
> >   - allocate memory for page tables.
> >
> > Three of them are part of boot data described by struct start_info.
> > Well, there are also other required stuff to properly boot PV guest.
> > So, I can agree that grub_xen_alloc_boot_data() is not perfect but
> > I cannot find anything better. Additionally, IMO grub_xen_alloc_kernel_mapping()
> > is not right choice too. It suggests that this functions does anything
> > with kernel mapping. Yep, it does, however, this is only one third
> > of this function. So, I tend to use my proposal or anything better
> > which is short and quite well describes what is going in this
> > function as whole.
>
> Yeah. grub_xen_alloc_stuff() with a nice comment. ;-)

:-))) I thought about that one too!

> Okay, lets stick with grub_xen_alloc_boot_data() and add a comment
> explaining that the function will allocate everything not yet allocated
> and covered by the initial page tables.

LGTM. Granted!

Daniel
diff mbox

Patch

diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
index 2e12763..466f0c0 100644
--- a/grub-core/loader/i386/xen.c
+++ b/grub-core/loader/i386/xen.c
@@ -228,6 +228,9 @@  grub_xen_p2m_alloc (void)
   grub_size_t p2msize;
   grub_err_t err;
 
+  if (xen_state.virt_mfn_list)
+    return GRUB_ERR_NONE;
+
   xen_state.state.mfn_list = xen_state.max_addr;
   xen_state.next_start.mfn_list =
     xen_state.max_addr + xen_state.xen_inf.virt_base;
@@ -250,6 +253,9 @@  grub_xen_special_alloc (void)
   grub_relocator_chunk_t ch;
   grub_err_t err;
 
+  if (xen_state.virt_start_info)
+    return GRUB_ERR_NONE;
+
   err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch,
 					 xen_state.max_addr,
 					 sizeof (xen_state.next_start));
@@ -281,6 +287,9 @@  grub_xen_pt_alloc (void)
   grub_uint64_t nr_info_pages;
   grub_uint64_t nr_pages, nr_pt_pages, nr_need_pages;
 
+  if (xen_state.virt_pgtable)
+    return GRUB_ERR_NONE;
+
   xen_state.next_start.pt_base =
     xen_state.max_addr + xen_state.xen_inf.virt_base;
   xen_state.state.paging_start = xen_state.max_addr >> PAGE_SHIFT;
@@ -320,6 +329,24 @@  grub_xen_pt_alloc (void)
 }
 
 static grub_err_t
+grub_xen_alloc_final (void)
+{
+  grub_err_t err;
+
+  err = grub_xen_p2m_alloc ();
+  if (err)
+    return err;
+  err = grub_xen_special_alloc ();
+  if (err)
+    return err;
+  err = grub_xen_pt_alloc ();
+  if (err)
+    return err;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
 grub_xen_boot (void)
 {
   grub_err_t err;
@@ -330,13 +357,7 @@  grub_xen_boot (void)
   if (grub_xen_n_allocated_shared_pages)
     return grub_error (GRUB_ERR_BUG, "active grants");
 
-  err = grub_xen_p2m_alloc ();
-  if (err)
-    return err;
-  err = grub_xen_special_alloc ();
-  if (err)
-    return err;
-  err = grub_xen_pt_alloc ();
+  err = grub_xen_alloc_final ();
   if (err)
     return err;
 
@@ -610,6 +631,13 @@  grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
       goto fail;
     }
 
+  if (xen_state.xen_inf.unmapped_initrd)
+    {
+      err = grub_xen_alloc_final ();
+      if (err)
+	goto fail;
+    }
+
   if (grub_initrd_init (argc, argv, &initrd_ctx))
     goto fail;
 
@@ -627,14 +655,24 @@  grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
 	goto fail;
     }
 
-  xen_state.next_start.mod_start =
-    xen_state.max_addr + xen_state.xen_inf.virt_base;
-  xen_state.next_start.mod_len = size;
-
-  xen_state.max_addr = ALIGN_UP (xen_state.max_addr + size, PAGE_SIZE);
+  if (xen_state.xen_inf.unmapped_initrd)
+    {
+      xen_state.next_start.flags |= SIF_MOD_START_PFN;
+      xen_state.next_start.mod_start = xen_state.max_addr >> PAGE_SHIFT;
+      xen_state.next_start.mod_len = size;
+    }
+  else
+    {
+      xen_state.next_start.mod_start =
+	xen_state.max_addr + xen_state.xen_inf.virt_base;
+      xen_state.next_start.mod_len = size;
+    }
 
   grub_dprintf ("xen", "Initrd, addr=0x%x, size=0x%x\n",
-		(unsigned) xen_state.next_start.mod_start, (unsigned) size);
+		(unsigned) (xen_state.max_addr + xen_state.xen_inf.virt_base),
+		(unsigned) size);
+
+  xen_state.max_addr = ALIGN_UP (xen_state.max_addr + size, PAGE_SIZE);
 
 fail:
   grub_initrd_close (&initrd_ctx);
@@ -686,6 +724,7 @@  grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
 
   if (!xen_state.module_info_page)
     {
+      xen_state.xen_inf.unmapped_initrd = 0;
       xen_state.n_modules = 0;
       xen_state.max_addr = ALIGN_UP (xen_state.max_addr, PAGE_SIZE);
       xen_state.modules_target_start = xen_state.max_addr;
diff --git a/grub-core/loader/i386/xen_fileXX.c b/grub-core/loader/i386/xen_fileXX.c
index 03215ca..8751174 100644
--- a/grub-core/loader/i386/xen_fileXX.c
+++ b/grub-core/loader/i386/xen_fileXX.c
@@ -261,6 +261,9 @@  parse_note (grub_elf_t elf, struct grub_xen_file_info *xi,
 					  descsz == 2 ? 2 : 3) == 0)
 	    xi->arch = GRUB_XEN_FILE_I386;
 	  break;
+	case XEN_ELFNOTE_MOD_START_PFN:
+	  xi->unmapped_initrd = !!grub_le_to_cpu32(*(grub_uint32_t *) desc);
+	  break;
 	default:
 	  grub_dprintf ("xen", "unknown note type %d\n", nh->n_type);
 	  break;
diff --git a/include/grub/xen_file.h b/include/grub/xen_file.h
index 4b2ccba..ed749fa 100644
--- a/include/grub/xen_file.h
+++ b/include/grub/xen_file.h
@@ -36,6 +36,7 @@  struct grub_xen_file_info
   int has_note;
   int has_xen_guest;
   int extended_cr3;
+  int unmapped_initrd;
   enum
   {
     GRUB_XEN_FILE_I386 = 1,