diff mbox series

[V4,1/1] riscv/efi_stub: Add support for RISCV_EFI_BOOT_PROTOCOL

Message ID 20220518095646.47548-2-sunilvl@ventanamicro.com (mailing list archive)
State New
Headers show
Series RISCV_EFI_BOOT_PROTOCOL support in linux | expand

Commit Message

Sunil V L May 18, 2022, 9:56 a.m. UTC
This patch adds the support for getting the boot hart ID in
Linux EFI stub using RISCV_EFI_BOOT_PROTOCOL. This protocol
is preferred method over existing DT based solution since it
works irrespective of DT or ACPI.

The specification of the protocol is hosted at:
https://github.com/riscv-non-isa/riscv-uefi

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
Reviewed-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
---
 drivers/firmware/efi/libstub/efistub.h    |  7 ++++++
 drivers/firmware/efi/libstub/riscv-stub.c | 29 +++++++++++++++++++----
 include/linux/efi.h                       |  1 +
 3 files changed, 32 insertions(+), 5 deletions(-)

Comments

Ard Biesheuvel May 18, 2022, 9:03 p.m. UTC | #1
On Wed, 18 May 2022 at 11:57, Sunil V L <sunilvl@ventanamicro.com> wrote:
>
> This patch adds the support for getting the boot hart ID in
> Linux EFI stub using RISCV_EFI_BOOT_PROTOCOL. This protocol
> is preferred method over existing DT based solution since it
> works irrespective of DT or ACPI.
>
> The specification of the protocol is hosted at:
> https://github.com/riscv-non-isa/riscv-uefi
>
> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
> Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
> Reviewed-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
> ---
>  drivers/firmware/efi/libstub/efistub.h    |  7 ++++++
>  drivers/firmware/efi/libstub/riscv-stub.c | 29 +++++++++++++++++++----
>  include/linux/efi.h                       |  1 +
>  3 files changed, 32 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
> index edb77b0621ea..aced62a0907e 100644
> --- a/drivers/firmware/efi/libstub/efistub.h
> +++ b/drivers/firmware/efi/libstub/efistub.h
> @@ -720,6 +720,13 @@ union efi_tcg2_protocol {
>         } mixed_mode;
>  };
>
> +struct riscv_efi_boot_protocol {
> +       u64 revision;
> +
> +       efi_status_t (__efiapi * get_boot_hartid)(struct riscv_efi_boot_protocol *this,
> +                                                 size_t *boot_hartid);

size_t is not a EFI type, and your spec uses UINTN here, which is
equivalent to 'unsigned long'. However, jump_kernel_func() takes a
unsigned int for the hartid. Please clean this up.


> +};
> +
>  typedef union efi_load_file_protocol efi_load_file_protocol_t;
>  typedef union efi_load_file_protocol efi_load_file2_protocol_t;
>
> diff --git a/drivers/firmware/efi/libstub/riscv-stub.c b/drivers/firmware/efi/libstub/riscv-stub.c
> index 9c460843442f..012504f6f9a4 100644
> --- a/drivers/firmware/efi/libstub/riscv-stub.c
> +++ b/drivers/firmware/efi/libstub/riscv-stub.c
> @@ -23,7 +23,7 @@
>
>  typedef void __noreturn (*jump_kernel_func)(unsigned int, unsigned long);
>
> -static u32 hartid;
> +static size_t hartid;
>

and here

>  static int get_boot_hartid_from_fdt(void)
>  {
> @@ -47,14 +47,33 @@ static int get_boot_hartid_from_fdt(void)
>         return 0;
>  }
>
> +static efi_status_t get_boot_hartid_from_efi(void)
> +{
> +       efi_guid_t boot_protocol_guid = RISCV_EFI_BOOT_PROTOCOL_GUID;
> +       efi_status_t status;
> +       struct riscv_efi_boot_protocol *boot_protocol;
> +
> +       status = efi_bs_call(locate_protocol, &boot_protocol_guid, NULL,
> +                            (void **)&boot_protocol);
> +       if (status == EFI_SUCCESS) {
> +               status = efi_call_proto(boot_protocol,
> +                                       get_boot_hartid, &hartid);
> +       }
> +       return status;
> +}
> +
>  efi_status_t check_platform_features(void)
>  {
>         int ret;
> +       efi_status_t status;
>
> -       ret = get_boot_hartid_from_fdt();
> -       if (ret) {
> -               efi_err("/chosen/boot-hartid missing or invalid!\n");
> -               return EFI_UNSUPPORTED;
> +       status = get_boot_hartid_from_efi();
> +       if (status != EFI_SUCCESS) {
> +               ret = get_boot_hartid_from_fdt();
> +               if (ret) {
> +                       efi_err("Failed to get boot hartid!\n");
> +                       return EFI_UNSUPPORTED;
> +               }
>         }
>         return EFI_SUCCESS;
>  }
> diff --git a/include/linux/efi.h b/include/linux/efi.h
> index ccd4d3f91c98..9822c730207c 100644
> --- a/include/linux/efi.h
> +++ b/include/linux/efi.h
> @@ -380,6 +380,7 @@ void efi_native_runtime_setup(void);
>  #define EFI_CONSOLE_OUT_DEVICE_GUID            EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4,  0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
>  #define APPLE_PROPERTIES_PROTOCOL_GUID         EFI_GUID(0x91bd12fe, 0xf6c3, 0x44fb,  0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 0xe0)
>  #define EFI_TCG2_PROTOCOL_GUID                 EFI_GUID(0x607f766c, 0x7455, 0x42be,  0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f)
> +#define RISCV_EFI_BOOT_PROTOCOL_GUID           EFI_GUID(0xccd15fec, 0x6f73, 0x4eec,  0x83, 0x95, 0x3e, 0x69, 0xe4, 0xb9, 0x40, 0xbf)
>  #define EFI_LOAD_FILE_PROTOCOL_GUID            EFI_GUID(0x56ec3091, 0x954c, 0x11d2,  0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
>  #define EFI_LOAD_FILE2_PROTOCOL_GUID           EFI_GUID(0x4006c0c1, 0xfcb3, 0x403e,  0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d)
>  #define EFI_RT_PROPERTIES_TABLE_GUID           EFI_GUID(0xeb66918a, 0x7eef, 0x402a,  0x84, 0x2e, 0x93, 0x1d, 0x21, 0xc3, 0x8a, 0xe9)
> --
> 2.25.1
>
Sunil V L May 19, 2022, 5:17 a.m. UTC | #2
On Wed, May 18, 2022 at 11:03:44PM +0200, Ard Biesheuvel wrote:
> On Wed, 18 May 2022 at 11:57, Sunil V L <sunilvl@ventanamicro.com> wrote:
> >
> > This patch adds the support for getting the boot hart ID in
> > Linux EFI stub using RISCV_EFI_BOOT_PROTOCOL. This protocol
> > is preferred method over existing DT based solution since it
> > works irrespective of DT or ACPI.
> >
> > The specification of the protocol is hosted at:
> > https://github.com/riscv-non-isa/riscv-uefi
> >
> > Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
> > Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
> > Reviewed-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
> > ---
> >  drivers/firmware/efi/libstub/efistub.h    |  7 ++++++
> >  drivers/firmware/efi/libstub/riscv-stub.c | 29 +++++++++++++++++++----
> >  include/linux/efi.h                       |  1 +
> >  3 files changed, 32 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
> > index edb77b0621ea..aced62a0907e 100644
> > --- a/drivers/firmware/efi/libstub/efistub.h
> > +++ b/drivers/firmware/efi/libstub/efistub.h
> > @@ -720,6 +720,13 @@ union efi_tcg2_protocol {
> >         } mixed_mode;
> >  };
> >
> > +struct riscv_efi_boot_protocol {
> > +       u64 revision;
> > +
> > +       efi_status_t (__efiapi * get_boot_hartid)(struct riscv_efi_boot_protocol *this,
> > +                                                 size_t *boot_hartid);
> 
> size_t is not a EFI type, and your spec uses UINTN here, which is
> equivalent to 'unsigned long'. However, jump_kernel_func() takes a
> unsigned int for the hartid. Please clean this up.
> 
Thank you Ard. Yes, hartid can be of native length. Have fixed this and
sent V5. Please check.

Thanks!
Sunil
> 
> > +};
> > +
> >  typedef union efi_load_file_protocol efi_load_file_protocol_t;
> >  typedef union efi_load_file_protocol efi_load_file2_protocol_t;
> >
> > diff --git a/drivers/firmware/efi/libstub/riscv-stub.c b/drivers/firmware/efi/libstub/riscv-stub.c
> > index 9c460843442f..012504f6f9a4 100644
> > --- a/drivers/firmware/efi/libstub/riscv-stub.c
> > +++ b/drivers/firmware/efi/libstub/riscv-stub.c
> > @@ -23,7 +23,7 @@
> >
> >  typedef void __noreturn (*jump_kernel_func)(unsigned int, unsigned long);
> >
> > -static u32 hartid;
> > +static size_t hartid;
> >
> 
> and here
> 
> >  static int get_boot_hartid_from_fdt(void)
> >  {
> > @@ -47,14 +47,33 @@ static int get_boot_hartid_from_fdt(void)
> >         return 0;
> >  }
> >
> > +static efi_status_t get_boot_hartid_from_efi(void)
> > +{
> > +       efi_guid_t boot_protocol_guid = RISCV_EFI_BOOT_PROTOCOL_GUID;
> > +       efi_status_t status;
> > +       struct riscv_efi_boot_protocol *boot_protocol;
> > +
> > +       status = efi_bs_call(locate_protocol, &boot_protocol_guid, NULL,
> > +                            (void **)&boot_protocol);
> > +       if (status == EFI_SUCCESS) {
> > +               status = efi_call_proto(boot_protocol,
> > +                                       get_boot_hartid, &hartid);
> > +       }
> > +       return status;
> > +}
> > +
> >  efi_status_t check_platform_features(void)
> >  {
> >         int ret;
> > +       efi_status_t status;
> >
> > -       ret = get_boot_hartid_from_fdt();
> > -       if (ret) {
> > -               efi_err("/chosen/boot-hartid missing or invalid!\n");
> > -               return EFI_UNSUPPORTED;
> > +       status = get_boot_hartid_from_efi();
> > +       if (status != EFI_SUCCESS) {
> > +               ret = get_boot_hartid_from_fdt();
> > +               if (ret) {
> > +                       efi_err("Failed to get boot hartid!\n");
> > +                       return EFI_UNSUPPORTED;
> > +               }
> >         }
> >         return EFI_SUCCESS;
> >  }
> > diff --git a/include/linux/efi.h b/include/linux/efi.h
> > index ccd4d3f91c98..9822c730207c 100644
> > --- a/include/linux/efi.h
> > +++ b/include/linux/efi.h
> > @@ -380,6 +380,7 @@ void efi_native_runtime_setup(void);
> >  #define EFI_CONSOLE_OUT_DEVICE_GUID            EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4,  0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
> >  #define APPLE_PROPERTIES_PROTOCOL_GUID         EFI_GUID(0x91bd12fe, 0xf6c3, 0x44fb,  0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 0xe0)
> >  #define EFI_TCG2_PROTOCOL_GUID                 EFI_GUID(0x607f766c, 0x7455, 0x42be,  0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f)
> > +#define RISCV_EFI_BOOT_PROTOCOL_GUID           EFI_GUID(0xccd15fec, 0x6f73, 0x4eec,  0x83, 0x95, 0x3e, 0x69, 0xe4, 0xb9, 0x40, 0xbf)
> >  #define EFI_LOAD_FILE_PROTOCOL_GUID            EFI_GUID(0x56ec3091, 0x954c, 0x11d2,  0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
> >  #define EFI_LOAD_FILE2_PROTOCOL_GUID           EFI_GUID(0x4006c0c1, 0xfcb3, 0x403e,  0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d)
> >  #define EFI_RT_PROPERTIES_TABLE_GUID           EFI_GUID(0xeb66918a, 0x7eef, 0x402a,  0x84, 0x2e, 0x93, 0x1d, 0x21, 0xc3, 0x8a, 0xe9)
> > --
> > 2.25.1
> >
Heinrich Schuchardt May 19, 2022, 6:17 a.m. UTC | #3
On 5/18/22 23:03, Ard Biesheuvel wrote:
> On Wed, 18 May 2022 at 11:57, Sunil V L <sunilvl@ventanamicro.com> wrote:
>>
>> This patch adds the support for getting the boot hart ID in
>> Linux EFI stub using RISCV_EFI_BOOT_PROTOCOL. This protocol
>> is preferred method over existing DT based solution since it
>> works irrespective of DT or ACPI.
>>
>> The specification of the protocol is hosted at:
>> https://github.com/riscv-non-isa/riscv-uefi
>>
>> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
>> Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
>> Reviewed-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
>> ---
>>   drivers/firmware/efi/libstub/efistub.h    |  7 ++++++
>>   drivers/firmware/efi/libstub/riscv-stub.c | 29 +++++++++++++++++++----
>>   include/linux/efi.h                       |  1 +
>>   3 files changed, 32 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
>> index edb77b0621ea..aced62a0907e 100644
>> --- a/drivers/firmware/efi/libstub/efistub.h
>> +++ b/drivers/firmware/efi/libstub/efistub.h
>> @@ -720,6 +720,13 @@ union efi_tcg2_protocol {
>>          } mixed_mode;
>>   };
>>
>> +struct riscv_efi_boot_protocol {
>> +       u64 revision;
>> +
>> +       efi_status_t (__efiapi * get_boot_hartid)(struct riscv_efi_boot_protocol *this,
>> +                                                 size_t *boot_hartid);
> 
> size_t is not a EFI type, and your spec uses UINTN here, which is
> equivalent to 'unsigned long'. However, jump_kernel_func() takes a
> unsigned int for the hartid. Please clean this up.

unsigned long and size_t have the same number of bits. This seems to be 
a question of taste where we should follow the maintainer.

jump_kernel_func() assuming boot hart ID to be an unsigned int is not in 
line with the RISC-V ISA which allows to use all xlen bits.

> 
> 
>> +};
>> +
>>   typedef union efi_load_file_protocol efi_load_file_protocol_t;
>>   typedef union efi_load_file_protocol efi_load_file2_protocol_t;
>>
>> diff --git a/drivers/firmware/efi/libstub/riscv-stub.c b/drivers/firmware/efi/libstub/riscv-stub.c
>> index 9c460843442f..012504f6f9a4 100644
>> --- a/drivers/firmware/efi/libstub/riscv-stub.c
>> +++ b/drivers/firmware/efi/libstub/riscv-stub.c
>> @@ -23,7 +23,7 @@
>>
>>   typedef void __noreturn (*jump_kernel_func)(unsigned int, unsigned long);
>>
>> -static u32 hartid;
>> +static size_t hartid;
>>
> 
> and here
> 
>>   static int get_boot_hartid_from_fdt(void)
>>   {
>> @@ -47,14 +47,33 @@ static int get_boot_hartid_from_fdt(void)
>>          return 0;
>>   }
>>
>> +static efi_status_t get_boot_hartid_from_efi(void)
>> +{
>> +       efi_guid_t boot_protocol_guid = RISCV_EFI_BOOT_PROTOCOL_GUID;
>> +       efi_status_t status;
>> +       struct riscv_efi_boot_protocol *boot_protocol;
>> +
>> +       status = efi_bs_call(locate_protocol, &boot_protocol_guid, NULL,
>> +                            (void **)&boot_protocol);
>> +       if (status == EFI_SUCCESS) {
>> +               status = efi_call_proto(boot_protocol,
>> +                                       get_boot_hartid, &hartid);

A lot of the kernel code seems to be unfit to handle hart IDs exceeding 
INT_MAX (e.g. sbi_cpu_is_stopped()). Until this is fixed we have to 
treat hartid > INT_MAX as an error.

Best regards

Heinrich

>> +       }
>> +       return status;
>> +}
>> +
>>   efi_status_t check_platform_features(void)
>>   {
>>          int ret;
>> +       efi_status_t status;
>>
>> -       ret = get_boot_hartid_from_fdt();
>> -       if (ret) {
>> -               efi_err("/chosen/boot-hartid missing or invalid!\n");
>> -               return EFI_UNSUPPORTED;
>> +       status = get_boot_hartid_from_efi();
>> +       if (status != EFI_SUCCESS) {
>> +               ret = get_boot_hartid_from_fdt();
>> +               if (ret) {
>> +                       efi_err("Failed to get boot hartid!\n");
>> +                       return EFI_UNSUPPORTED;
>> +               }
>>          }
>>          return EFI_SUCCESS;
>>   }
>> diff --git a/include/linux/efi.h b/include/linux/efi.h
>> index ccd4d3f91c98..9822c730207c 100644
>> --- a/include/linux/efi.h
>> +++ b/include/linux/efi.h
>> @@ -380,6 +380,7 @@ void efi_native_runtime_setup(void);
>>   #define EFI_CONSOLE_OUT_DEVICE_GUID            EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4,  0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
>>   #define APPLE_PROPERTIES_PROTOCOL_GUID         EFI_GUID(0x91bd12fe, 0xf6c3, 0x44fb,  0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 0xe0)
>>   #define EFI_TCG2_PROTOCOL_GUID                 EFI_GUID(0x607f766c, 0x7455, 0x42be,  0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f)
>> +#define RISCV_EFI_BOOT_PROTOCOL_GUID           EFI_GUID(0xccd15fec, 0x6f73, 0x4eec,  0x83, 0x95, 0x3e, 0x69, 0xe4, 0xb9, 0x40, 0xbf)
>>   #define EFI_LOAD_FILE_PROTOCOL_GUID            EFI_GUID(0x56ec3091, 0x954c, 0x11d2,  0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
>>   #define EFI_LOAD_FILE2_PROTOCOL_GUID           EFI_GUID(0x4006c0c1, 0xfcb3, 0x403e,  0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d)
>>   #define EFI_RT_PROPERTIES_TABLE_GUID           EFI_GUID(0xeb66918a, 0x7eef, 0x402a,  0x84, 0x2e, 0x93, 0x1d, 0x21, 0xc3, 0x8a, 0xe9)
>> --
>> 2.25.1
>>
Ard Biesheuvel May 19, 2022, 8:13 a.m. UTC | #4
On Thu, 19 May 2022 at 08:17, Heinrich Schuchardt
<heinrich.schuchardt@canonical.com> wrote:
>
>
>
> On 5/18/22 23:03, Ard Biesheuvel wrote:
> > On Wed, 18 May 2022 at 11:57, Sunil V L <sunilvl@ventanamicro.com> wrote:
> >>
> >> This patch adds the support for getting the boot hart ID in
> >> Linux EFI stub using RISCV_EFI_BOOT_PROTOCOL. This protocol
> >> is preferred method over existing DT based solution since it
> >> works irrespective of DT or ACPI.
> >>
> >> The specification of the protocol is hosted at:
> >> https://github.com/riscv-non-isa/riscv-uefi
> >>
> >> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
> >> Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
> >> Reviewed-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
> >> ---
> >>   drivers/firmware/efi/libstub/efistub.h    |  7 ++++++
> >>   drivers/firmware/efi/libstub/riscv-stub.c | 29 +++++++++++++++++++----
> >>   include/linux/efi.h                       |  1 +
> >>   3 files changed, 32 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
> >> index edb77b0621ea..aced62a0907e 100644
> >> --- a/drivers/firmware/efi/libstub/efistub.h
> >> +++ b/drivers/firmware/efi/libstub/efistub.h
> >> @@ -720,6 +720,13 @@ union efi_tcg2_protocol {
> >>          } mixed_mode;
> >>   };
> >>
> >> +struct riscv_efi_boot_protocol {
> >> +       u64 revision;
> >> +
> >> +       efi_status_t (__efiapi * get_boot_hartid)(struct riscv_efi_boot_protocol *this,
> >> +                                                 size_t *boot_hartid);
> >
> > size_t is not a EFI type, and your spec uses UINTN here, which is
> > equivalent to 'unsigned long'. However, jump_kernel_func() takes a
> > unsigned int for the hartid. Please clean this up.
>
> unsigned long and size_t have the same number of bits. This seems to be
> a question of taste where we should follow the maintainer.
>

We use unsigned long wherever the UEFI spec uses UINTN. This is not a
matter of taste, really.

> jump_kernel_func() assuming boot hart ID to be an unsigned int is not in
> line with the RISC-V ISA which allows to use all xlen bits.
>
> >
> >
> >> +};
> >> +
> >>   typedef union efi_load_file_protocol efi_load_file_protocol_t;
> >>   typedef union efi_load_file_protocol efi_load_file2_protocol_t;
> >>
> >> diff --git a/drivers/firmware/efi/libstub/riscv-stub.c b/drivers/firmware/efi/libstub/riscv-stub.c
> >> index 9c460843442f..012504f6f9a4 100644
> >> --- a/drivers/firmware/efi/libstub/riscv-stub.c
> >> +++ b/drivers/firmware/efi/libstub/riscv-stub.c
> >> @@ -23,7 +23,7 @@
> >>
> >>   typedef void __noreturn (*jump_kernel_func)(unsigned int, unsigned long);
> >>
> >> -static u32 hartid;
> >> +static size_t hartid;
> >>
> >
> > and here
> >
> >>   static int get_boot_hartid_from_fdt(void)
> >>   {
> >> @@ -47,14 +47,33 @@ static int get_boot_hartid_from_fdt(void)
> >>          return 0;
> >>   }
> >>
> >> +static efi_status_t get_boot_hartid_from_efi(void)
> >> +{
> >> +       efi_guid_t boot_protocol_guid = RISCV_EFI_BOOT_PROTOCOL_GUID;
> >> +       efi_status_t status;
> >> +       struct riscv_efi_boot_protocol *boot_protocol;
> >> +
> >> +       status = efi_bs_call(locate_protocol, &boot_protocol_guid, NULL,
> >> +                            (void **)&boot_protocol);
> >> +       if (status == EFI_SUCCESS) {
> >> +               status = efi_call_proto(boot_protocol,
> >> +                                       get_boot_hartid, &hartid);
>
> A lot of the kernel code seems to be unfit to handle hart IDs exceeding
> INT_MAX (e.g. sbi_cpu_is_stopped()). Until this is fixed we have to
> treat hartid > INT_MAX as an error.
>

This is an issue in the core kernel code, not in the EFI stub. As you
pointed out, the ISA implies UINTN / unsigned long here, and if the
startup code cannot deal with that, it can be fixed separately.
Atish Patra May 19, 2022, 6:07 p.m. UTC | #5
On Thu, May 19, 2022 at 1:14 AM Ard Biesheuvel <ardb@kernel.org> wrote:
>
> On Thu, 19 May 2022 at 08:17, Heinrich Schuchardt
> <heinrich.schuchardt@canonical.com> wrote:
> >
> >
> >
> > On 5/18/22 23:03, Ard Biesheuvel wrote:
> > > On Wed, 18 May 2022 at 11:57, Sunil V L <sunilvl@ventanamicro.com> wrote:
> > >>
> > >> This patch adds the support for getting the boot hart ID in
> > >> Linux EFI stub using RISCV_EFI_BOOT_PROTOCOL. This protocol
> > >> is preferred method over existing DT based solution since it
> > >> works irrespective of DT or ACPI.
> > >>
> > >> The specification of the protocol is hosted at:
> > >> https://github.com/riscv-non-isa/riscv-uefi
> > >>
> > >> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
> > >> Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
> > >> Reviewed-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
> > >> ---
> > >>   drivers/firmware/efi/libstub/efistub.h    |  7 ++++++
> > >>   drivers/firmware/efi/libstub/riscv-stub.c | 29 +++++++++++++++++++----
> > >>   include/linux/efi.h                       |  1 +
> > >>   3 files changed, 32 insertions(+), 5 deletions(-)
> > >>
> > >> diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
> > >> index edb77b0621ea..aced62a0907e 100644
> > >> --- a/drivers/firmware/efi/libstub/efistub.h
> > >> +++ b/drivers/firmware/efi/libstub/efistub.h
> > >> @@ -720,6 +720,13 @@ union efi_tcg2_protocol {
> > >>          } mixed_mode;
> > >>   };
> > >>
> > >> +struct riscv_efi_boot_protocol {
> > >> +       u64 revision;
> > >> +
> > >> +       efi_status_t (__efiapi * get_boot_hartid)(struct riscv_efi_boot_protocol *this,
> > >> +                                                 size_t *boot_hartid);
> > >
> > > size_t is not a EFI type, and your spec uses UINTN here, which is
> > > equivalent to 'unsigned long'. However, jump_kernel_func() takes a
> > > unsigned int for the hartid. Please clean this up.
> >
> > unsigned long and size_t have the same number of bits. This seems to be
> > a question of taste where we should follow the maintainer.
> >
>
> We use unsigned long wherever the UEFI spec uses UINTN. This is not a
> matter of taste, really.
>
> > jump_kernel_func() assuming boot hart ID to be an unsigned int is not in
> > line with the RISC-V ISA which allows to use all xlen bits.
> >
> > >
> > >
> > >> +};
> > >> +
> > >>   typedef union efi_load_file_protocol efi_load_file_protocol_t;
> > >>   typedef union efi_load_file_protocol efi_load_file2_protocol_t;
> > >>
> > >> diff --git a/drivers/firmware/efi/libstub/riscv-stub.c b/drivers/firmware/efi/libstub/riscv-stub.c
> > >> index 9c460843442f..012504f6f9a4 100644
> > >> --- a/drivers/firmware/efi/libstub/riscv-stub.c
> > >> +++ b/drivers/firmware/efi/libstub/riscv-stub.c
> > >> @@ -23,7 +23,7 @@
> > >>
> > >>   typedef void __noreturn (*jump_kernel_func)(unsigned int, unsigned long);
> > >>
> > >> -static u32 hartid;
> > >> +static size_t hartid;
> > >>
> > >
> > > and here
> > >
> > >>   static int get_boot_hartid_from_fdt(void)
> > >>   {
> > >> @@ -47,14 +47,33 @@ static int get_boot_hartid_from_fdt(void)
> > >>          return 0;
> > >>   }
> > >>
> > >> +static efi_status_t get_boot_hartid_from_efi(void)
> > >> +{
> > >> +       efi_guid_t boot_protocol_guid = RISCV_EFI_BOOT_PROTOCOL_GUID;
> > >> +       efi_status_t status;
> > >> +       struct riscv_efi_boot_protocol *boot_protocol;
> > >> +
> > >> +       status = efi_bs_call(locate_protocol, &boot_protocol_guid, NULL,
> > >> +                            (void **)&boot_protocol);
> > >> +       if (status == EFI_SUCCESS) {
> > >> +               status = efi_call_proto(boot_protocol,
> > >> +                                       get_boot_hartid, &hartid);
> >
> > A lot of the kernel code seems to be unfit to handle hart IDs exceeding
> > INT_MAX (e.g. sbi_cpu_is_stopped()). Until this is fixed we have to
> > treat hartid > INT_MAX as an error.
> >
>
> This is an issue in the core kernel code, not in the EFI stub. As you
> pointed out, the ISA implies UINTN / unsigned long here, and if the
> startup code cannot deal with that, it can be fixed separately.

It was kept as unsigned int because hartid > INT_MAX is very unlikely to happen.
But I agree that we should just follow the spec(allowing XLEN bits for
hartid) and
change "unsigned int" to "unsigned long" wherever hartid is concerned.

As the hartid is changed to unsigned long, get_boot_hartid_from_fdt
should be fixed as well.
Currently, it is using fdt32_to_cpu.



--
Regards,
Atish
Sunil V L May 20, 2022, 4:43 a.m. UTC | #6
On Thu, May 19, 2022 at 11:07:28AM -0700, Atish Patra wrote:
> On Thu, May 19, 2022 at 1:14 AM Ard Biesheuvel <ardb@kernel.org> wrote:
> >
> > On Thu, 19 May 2022 at 08:17, Heinrich Schuchardt
> > <heinrich.schuchardt@canonical.com> wrote:
> > >
> > >
> > >
> > > On 5/18/22 23:03, Ard Biesheuvel wrote:
> > > > On Wed, 18 May 2022 at 11:57, Sunil V L <sunilvl@ventanamicro.com> wrote:
> > > >>
> > > >> This patch adds the support for getting the boot hart ID in
> > > >> Linux EFI stub using RISCV_EFI_BOOT_PROTOCOL. This protocol
> > > >> is preferred method over existing DT based solution since it
> > > >> works irrespective of DT or ACPI.
> > > >>
> > > >> The specification of the protocol is hosted at:
> > > >> https://github.com/riscv-non-isa/riscv-uefi
> > > >>
> > > >> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
> > > >> Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
> > > >> Reviewed-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
> > > >> ---
> > > >>   drivers/firmware/efi/libstub/efistub.h    |  7 ++++++
> > > >>   drivers/firmware/efi/libstub/riscv-stub.c | 29 +++++++++++++++++++----
> > > >>   include/linux/efi.h                       |  1 +
> > > >>   3 files changed, 32 insertions(+), 5 deletions(-)
> > > >>
> > > >> diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
> > > >> index edb77b0621ea..aced62a0907e 100644
> > > >> --- a/drivers/firmware/efi/libstub/efistub.h
> > > >> +++ b/drivers/firmware/efi/libstub/efistub.h
> > > >> @@ -720,6 +720,13 @@ union efi_tcg2_protocol {
> > > >>          } mixed_mode;
> > > >>   };
> > > >>
> > > >> +struct riscv_efi_boot_protocol {
> > > >> +       u64 revision;
> > > >> +
> > > >> +       efi_status_t (__efiapi * get_boot_hartid)(struct riscv_efi_boot_protocol *this,
> > > >> +                                                 size_t *boot_hartid);
> > > >
> > > > size_t is not a EFI type, and your spec uses UINTN here, which is
> > > > equivalent to 'unsigned long'. However, jump_kernel_func() takes a
> > > > unsigned int for the hartid. Please clean this up.
> > >
> > > unsigned long and size_t have the same number of bits. This seems to be
> > > a question of taste where we should follow the maintainer.
> > >
> >
> > We use unsigned long wherever the UEFI spec uses UINTN. This is not a
> > matter of taste, really.
> >
> > > jump_kernel_func() assuming boot hart ID to be an unsigned int is not in
> > > line with the RISC-V ISA which allows to use all xlen bits.
> > >
> > > >
> > > >
> > > >> +};
> > > >> +
> > > >>   typedef union efi_load_file_protocol efi_load_file_protocol_t;
> > > >>   typedef union efi_load_file_protocol efi_load_file2_protocol_t;
> > > >>
> > > >> diff --git a/drivers/firmware/efi/libstub/riscv-stub.c b/drivers/firmware/efi/libstub/riscv-stub.c
> > > >> index 9c460843442f..012504f6f9a4 100644
> > > >> --- a/drivers/firmware/efi/libstub/riscv-stub.c
> > > >> +++ b/drivers/firmware/efi/libstub/riscv-stub.c
> > > >> @@ -23,7 +23,7 @@
> > > >>
> > > >>   typedef void __noreturn (*jump_kernel_func)(unsigned int, unsigned long);
> > > >>
> > > >> -static u32 hartid;
> > > >> +static size_t hartid;
> > > >>
> > > >
> > > > and here
> > > >
> > > >>   static int get_boot_hartid_from_fdt(void)
> > > >>   {
> > > >> @@ -47,14 +47,33 @@ static int get_boot_hartid_from_fdt(void)
> > > >>          return 0;
> > > >>   }
> > > >>
> > > >> +static efi_status_t get_boot_hartid_from_efi(void)
> > > >> +{
> > > >> +       efi_guid_t boot_protocol_guid = RISCV_EFI_BOOT_PROTOCOL_GUID;
> > > >> +       efi_status_t status;
> > > >> +       struct riscv_efi_boot_protocol *boot_protocol;
> > > >> +
> > > >> +       status = efi_bs_call(locate_protocol, &boot_protocol_guid, NULL,
> > > >> +                            (void **)&boot_protocol);
> > > >> +       if (status == EFI_SUCCESS) {
> > > >> +               status = efi_call_proto(boot_protocol,
> > > >> +                                       get_boot_hartid, &hartid);
> > >
> > > A lot of the kernel code seems to be unfit to handle hart IDs exceeding
> > > INT_MAX (e.g. sbi_cpu_is_stopped()). Until this is fixed we have to
> > > treat hartid > INT_MAX as an error.
> > >
> >
> > This is an issue in the core kernel code, not in the EFI stub. As you
> > pointed out, the ISA implies UINTN / unsigned long here, and if the
> > startup code cannot deal with that, it can be fixed separately.
> 
> It was kept as unsigned int because hartid > INT_MAX is very unlikely to happen.
> But I agree that we should just follow the spec(allowing XLEN bits for
> hartid) and
> change "unsigned int" to "unsigned long" wherever hartid is concerned.
> 
> As the hartid is changed to unsigned long, get_boot_hartid_from_fdt
> should be fixed as well.
> Currently, it is using fdt32_to_cpu.

I am working on a separate patch series to modify these instances. Will send
soon for your feedback.

Thanks
Sunil
> 
> 
> 
> --
> Regards,
> Atish
diff mbox series

Patch

diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index edb77b0621ea..aced62a0907e 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -720,6 +720,13 @@  union efi_tcg2_protocol {
 	} mixed_mode;
 };
 
+struct riscv_efi_boot_protocol {
+	u64 revision;
+
+	efi_status_t (__efiapi * get_boot_hartid)(struct riscv_efi_boot_protocol *this,
+						  size_t *boot_hartid);
+};
+
 typedef union efi_load_file_protocol efi_load_file_protocol_t;
 typedef union efi_load_file_protocol efi_load_file2_protocol_t;
 
diff --git a/drivers/firmware/efi/libstub/riscv-stub.c b/drivers/firmware/efi/libstub/riscv-stub.c
index 9c460843442f..012504f6f9a4 100644
--- a/drivers/firmware/efi/libstub/riscv-stub.c
+++ b/drivers/firmware/efi/libstub/riscv-stub.c
@@ -23,7 +23,7 @@ 
 
 typedef void __noreturn (*jump_kernel_func)(unsigned int, unsigned long);
 
-static u32 hartid;
+static size_t hartid;
 
 static int get_boot_hartid_from_fdt(void)
 {
@@ -47,14 +47,33 @@  static int get_boot_hartid_from_fdt(void)
 	return 0;
 }
 
+static efi_status_t get_boot_hartid_from_efi(void)
+{
+	efi_guid_t boot_protocol_guid = RISCV_EFI_BOOT_PROTOCOL_GUID;
+	efi_status_t status;
+	struct riscv_efi_boot_protocol *boot_protocol;
+
+	status = efi_bs_call(locate_protocol, &boot_protocol_guid, NULL,
+			     (void **)&boot_protocol);
+	if (status == EFI_SUCCESS) {
+		status = efi_call_proto(boot_protocol,
+					get_boot_hartid, &hartid);
+	}
+	return status;
+}
+
 efi_status_t check_platform_features(void)
 {
 	int ret;
+	efi_status_t status;
 
-	ret = get_boot_hartid_from_fdt();
-	if (ret) {
-		efi_err("/chosen/boot-hartid missing or invalid!\n");
-		return EFI_UNSUPPORTED;
+	status = get_boot_hartid_from_efi();
+	if (status != EFI_SUCCESS) {
+		ret = get_boot_hartid_from_fdt();
+		if (ret) {
+			efi_err("Failed to get boot hartid!\n");
+			return EFI_UNSUPPORTED;
+		}
 	}
 	return EFI_SUCCESS;
 }
diff --git a/include/linux/efi.h b/include/linux/efi.h
index ccd4d3f91c98..9822c730207c 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -380,6 +380,7 @@  void efi_native_runtime_setup(void);
 #define EFI_CONSOLE_OUT_DEVICE_GUID		EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4,  0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
 #define APPLE_PROPERTIES_PROTOCOL_GUID		EFI_GUID(0x91bd12fe, 0xf6c3, 0x44fb,  0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 0xe0)
 #define EFI_TCG2_PROTOCOL_GUID			EFI_GUID(0x607f766c, 0x7455, 0x42be,  0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f)
+#define RISCV_EFI_BOOT_PROTOCOL_GUID		EFI_GUID(0xccd15fec, 0x6f73, 0x4eec,  0x83, 0x95, 0x3e, 0x69, 0xe4, 0xb9, 0x40, 0xbf)
 #define EFI_LOAD_FILE_PROTOCOL_GUID		EFI_GUID(0x56ec3091, 0x954c, 0x11d2,  0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
 #define EFI_LOAD_FILE2_PROTOCOL_GUID		EFI_GUID(0x4006c0c1, 0xfcb3, 0x403e,  0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d)
 #define EFI_RT_PROPERTIES_TABLE_GUID		EFI_GUID(0xeb66918a, 0x7eef, 0x402a,  0x84, 0x2e, 0x93, 0x1d, 0x21, 0xc3, 0x8a, 0xe9)