Re: [RFC v2 1/2] riscv: allow resume after exception

2023-10-31 Thread Xiang W
Thank you, I understand.

Regards,
Xiang W

Heinrich Schuchardt  于2023年10月31日周二 20:09写道:
>
> On 10/31/23 09:53, Xiang W wrote:
> > setjmp can be called in set_resume.
>
> Unfortunately this is not possible. A longjmp buffer only stores
> register values and not the stack content.
>
> Let's assume that setjmp() is moved into set_resume():
>
> Let a function call set_resume(). The caller's address will be on the
> stack. Once the set_resume returns and the caller invokes another
> function the original stack content will be overwritten. When an
> exception occurs the longjmp will reenter set_resume() with the original
> stack pointer value pointing to a stack that does not match the original
> call to set_resume and set_resume will return to a random address.
>
> Best regards
>
> Heinrich
>
> >
> > Regards,
> > Xiang W
> >
> > Heinrich Schuchardt  于2023年10月29日周日 
> > 16:56写道:
> >>
> >> If CSRs like seed are readable by S-mode, may not be determinable by
> >> S-mode. For safe driver probing allow to resume via a longjmp after an
> >> exception.
> >>
> >> Signed-off-by: Heinrich Schuchardt 
> >> ---
> >> v2:
> >>  new patch
> >> ---
> >>   arch/riscv/lib/interrupts.c | 13 +
> >>   include/interrupt.h | 22 ++
> >>   2 files changed, 35 insertions(+)
> >>   create mode 100644 include/interrupt.h
> >>
> >> diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c
> >> index 02dbcfd423..a26ccc721f 100644
> >> --- a/arch/riscv/lib/interrupts.c
> >> +++ b/arch/riscv/lib/interrupts.c
> >> @@ -12,6 +12,7 @@
> >>   #include 
> >>   #include 
> >>   #include 
> >> +#include 
> >>   #include 
> >>   #include 
> >>   #include 
> >> @@ -21,6 +22,13 @@
> >>
> >>   DECLARE_GLOBAL_DATA_PTR;
> >>
> >> +static struct resume_data *resume;
> >> +
> >> +void set_resume(struct resume_data *data)
> >> +{
> >> +   resume = data;
> >> +}
> >> +
> >>   static void show_efi_loaded_images(uintptr_t epc)
> >>   {
> >>  efi_print_image_infos((void *)epc);
> >> @@ -105,6 +113,11 @@ static void _exit_trap(ulong code, ulong epc, ulong 
> >> tval, struct pt_regs *regs)
> >>  "Store/AMO page fault",
> >>  };
> >>
> >> +   if (resume) {
> >> +   resume->code = code;
> >> +   longjmp(resume->jump, 1);
> >> +   }
> >> +
> >>  if (code < ARRAY_SIZE(exception_code))
> >>  printf("Unhandled exception: %s\n", exception_code[code]);
> >>  else
> >> diff --git a/include/interrupt.h b/include/interrupt.h
> >> new file mode 100644
> >> index 00..1baa60bcf2
> >> --- /dev/null
> >> +++ b/include/interrupt.h
> >> @@ -0,0 +1,22 @@
> >> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> >> +
> >> +#include 
> >> +
> >> +/**
> >> + * struct resume_data - data for resume after interrupt
> >> + */
> >> +struct resume_data {
> >> +   /** @jump: longjmp buffer */
> >> +   jmp_buf jump;
> >> +   /** @code: exception code */
> >> +   ulong code;
> >> +};
> >> +
> >> +/**
> >> + * set_resume() - set longjmp buffer for resuming after interrupt
> >> + *
> >> + * When resuming the exception code will be returned in @data->code.
> >> + *
> >> + * @data:  pointer to structure with longjmp address
> >> + */
> >> +void set_resume(struct resume_data *data);
> >> --
> >> 2.40.1
> >>
>


Re: [RFC v2 2/2] rng: Provide a RNG based on the RISC-V Zkr ISA extension

2023-10-31 Thread Xiang W
Sorry! I missed it.

Regards,
Xiang W

Leo Liang  于2023年10月31日周二 14:47写道:
>
> Hi Xiang,
> On Tue, Oct 31, 2023 at 02:16:22PM +0800, merle w wrote:
> > drivers/rng/riscv_zkr_rng.c:10:10: fatal error: interrupt.h: No such
> > file or directory
> > 10 | #include 
> > | ^
> > compilation terminated.
> >
> > Where is this interrupt.h?
>
> I think this file is created by the first patch of this patchset.
> "[RFC,v2,1/2] riscv: allow resume after exception"
>
> Could you try to apply this patch and then test again?
> It should compile without error.
>
> Best regards,
> Leo
>
> >
> > Regards,
> > Xiang W
> >
> > Heinrich Schuchardt  于2023年10月29日周日 
> > 16:46写道:
> > >
> > > The Zkr ISA extension (ratified Nov 2021) introduced the seed CSR. It
> > > provides an interface to a physical entropy source.
> > >
> > > A RNG driver based on the seed CSR is provided. It depends on
> > > mseccfg.sseed being set in the SBI firmware.
> > >
> > > Signed-off-by: Heinrich Schuchardt 
> > > ---
> > > v2:
> > > Resume after exception if seed CSR cannot be read.
> > > ---
> > >  drivers/rng/Kconfig |   8 +++
> > >  drivers/rng/Makefile|   1 +
> > >  drivers/rng/riscv_zkr_rng.c | 116 
> > >  3 files changed, 125 insertions(+)
> > >  create mode 100644 drivers/rng/riscv_zkr_rng.c
> > >
> > > diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig
> > > index 994cc35b27..4f6e367169 100644
> > > --- a/drivers/rng/Kconfig
> > > +++ b/drivers/rng/Kconfig
> > > @@ -48,6 +48,14 @@ config RNG_OPTEE
> > >   accessible to normal world but reserved and used by the OP-TEE
> > >   to avoid the weakness of a software PRNG.
> > >
> > > +config RNG_RISCV_ZKR
> > > +   bool "RISC-V Zkr random number generator"
> > > +   depends on RISCV_SMODE
> > > +   help
> > > + This driver provides a Random Number Generator based on the
> > > + Zkr RISC-V ISA extension which provides an interface to an
> > > + NIST SP 800-90B or BSI AIS-31 compliant physical entropy source.
> > > +
> > >  config RNG_STM32
> > > bool "Enable random number generator for STM32"
> > > depends on ARCH_STM32 || ARCH_STM32MP
> > > diff --git a/drivers/rng/Makefile b/drivers/rng/Makefile
> > > index 47b323e61e..a5d3ca4130 100644
> > > --- a/drivers/rng/Makefile
> > > +++ b/drivers/rng/Makefile
> > > @@ -10,6 +10,7 @@ obj-$(CONFIG_RNG_MSM) += msm_rng.o
> > >  obj-$(CONFIG_RNG_NPCM) += npcm_rng.o
> > >  obj-$(CONFIG_RNG_OPTEE) += optee_rng.o
> > >  obj-$(CONFIG_RNG_STM32) += stm32_rng.o
> > > +obj-$(CONFIG_RNG_RISCV_ZKR) += riscv_zkr_rng.o
> > >  obj-$(CONFIG_RNG_ROCKCHIP) += rockchip_rng.o
> > >  obj-$(CONFIG_RNG_IPROC200) += iproc_rng200.o
> > >  obj-$(CONFIG_RNG_SMCCC_TRNG) += smccc_trng.o
> > > diff --git a/drivers/rng/riscv_zkr_rng.c b/drivers/rng/riscv_zkr_rng.c
> > > new file mode 100644
> > > index 00..8c9e111e2e
> > > --- /dev/null
> > > +++ b/drivers/rng/riscv_zkr_rng.c
> > > @@ -0,0 +1,116 @@
> > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > +/*
> > > + * The RISC-V Zkr extension provides CSR seed which provides access to a
> > > + * random number generator.
> > > + */
> > > +
> > > +#define LOG_CATEGORY UCLASS_RNG
> > > +
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +
> > > +#define DRIVER_NAME "riscv_zkr"
> > > +
> > > +enum opst {
> > > +   /** @BIST: built in self test running */
> > > +   BIST = 0b00,
> > > +   /** @WAIT: sufficient amount of entropy is not yet available */
> > > +   WAIT = 0b01,
> > > +   /** @ES16: 16bits of entropy available */
> > > +   ES16 = 0b10,
> > > +   /** @DEAD: unrecoverable self-test error */
> > > +   DEAD = 0b11,
> > > +};
> > > +
> > > +static unsigned long read_seed(void)
> > > +{
> > > +   unsigned long ret;
> > > +
> > > +   __asm__ __volatile__("csrrw %0, seed, x0" : "=r" (ret) : : 
> > > "memory");
> > > +
> > > +   return ret;
> 

Re: [RFC v2 1/2] riscv: allow resume after exception

2023-10-31 Thread Xiang W
setjmp can be called in set_resume.

Regards,
Xiang W

Heinrich Schuchardt  于2023年10月29日周日 16:56写道:
>
> If CSRs like seed are readable by S-mode, may not be determinable by
> S-mode. For safe driver probing allow to resume via a longjmp after an
> exception.
>
> Signed-off-by: Heinrich Schuchardt 
> ---
> v2:
> new patch
> ---
>  arch/riscv/lib/interrupts.c | 13 +
>  include/interrupt.h | 22 ++
>  2 files changed, 35 insertions(+)
>  create mode 100644 include/interrupt.h
>
> diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c
> index 02dbcfd423..a26ccc721f 100644
> --- a/arch/riscv/lib/interrupts.c
> +++ b/arch/riscv/lib/interrupts.c
> @@ -12,6 +12,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -21,6 +22,13 @@
>
>  DECLARE_GLOBAL_DATA_PTR;
>
> +static struct resume_data *resume;
> +
> +void set_resume(struct resume_data *data)
> +{
> +   resume = data;
> +}
> +
>  static void show_efi_loaded_images(uintptr_t epc)
>  {
> efi_print_image_infos((void *)epc);
> @@ -105,6 +113,11 @@ static void _exit_trap(ulong code, ulong epc, ulong 
> tval, struct pt_regs *regs)
> "Store/AMO page fault",
> };
>
> +   if (resume) {
> +   resume->code = code;
> +   longjmp(resume->jump, 1);
> +   }
> +
> if (code < ARRAY_SIZE(exception_code))
> printf("Unhandled exception: %s\n", exception_code[code]);
> else
> diff --git a/include/interrupt.h b/include/interrupt.h
> new file mode 100644
> index 00..1baa60bcf2
> --- /dev/null
> +++ b/include/interrupt.h
> @@ -0,0 +1,22 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +
> +#include 
> +
> +/**
> + * struct resume_data - data for resume after interrupt
> + */
> +struct resume_data {
> +   /** @jump: longjmp buffer */
> +   jmp_buf jump;
> +   /** @code: exception code */
> +   ulong code;
> +};
> +
> +/**
> + * set_resume() - set longjmp buffer for resuming after interrupt
> + *
> + * When resuming the exception code will be returned in @data->code.
> + *
> + * @data:  pointer to structure with longjmp address
> + */
> +void set_resume(struct resume_data *data);
> --
> 2.40.1
>


Re: [PATCH v2] riscv: cancel the limitation that NR_CPUS is less than or equal to 32

2023-02-11 Thread Xiang W
在 2023-02-10星期五的 07:25 +,Leo Liang写道:
> Hi Xiang,
> 
> On Fri, Feb 03, 2023 at 03:24:37PM +0100, David Abdurachmanov wrote:
> > On Mon, Jan 3, 2022 at 1:13 PM Leo Liang  wrote:
> > > 
> > > On Thu, Dec 30, 2021 at 01:55:15AM +0800, Xiang W wrote:
> > > > 在 2021-12-29星期三的 17:23 +0800,Leo Liang写道:
> > > > > Hi Xiang,
> > > > > On Wed, Dec 22, 2021 at 07:32:53AM +0800, Xiang W wrote:
> > > > > > Various specifications of riscv allow the number of hart to be
> > > > > > greater than 32. The limit of 32 is determined by
> > > > > > gd->arch.available_harts. We can eliminate this limitation through
> > > > > > bitmaps. Currently, the number of hart is limited to 4095, and 4095
> > > > > > is the limit of the RISC-V Advanced Core Local Interruptor
> > > > > > Specification.
> > > > > > 
> > > > > > Test on sifive unmatched.
> > > > > > 
> > > > > > Signed-off-by: Xiang W 
> > > > > > ---
> > > > > > Changes since v1:
> > > > > > 
> > > > > > * When NR_CPUS is very large, the value of GD_AVAILABLE_HARTS will
> > > > > >   overflow the immediate range of ld/lw. This patch fixes this
> > > > > >   problem
> > > > > > 
> > > > > >  arch/riscv/Kconfig   |  4 ++--
> > > > > >  arch/riscv/cpu/start.S   | 21 -
> > > > > >  arch/riscv/include/asm/global_data.h |  4 +++-
> > > > > >  arch/riscv/lib/smp.c |  2 +-
> > > > > >  4 files changed, 22 insertions(+), 9 deletions(-)
> > > > > > 
> > 
> > I noticed that this has never landed in U-Boot. Was this forgotten or
> > dropped for some reason (couldn't find anything)?
> > 
> > The current limit on the Linux kernel side is 512. The default on
> > 64-bit (riscv64) is 64.
> > 
> > david
> 
> The patch seems to cause some CI error (timeout on QEMU).
> (https://source.denx.de/u-boot/custodians/u-boot-riscv/-/pipelines/15076)
> Could you take a look at it if you have time?
> 
> Best regards,
> Leo

sorry! I missing a bug. There is an error in calculating the starting address
of available_harts. The patch for start.S needs to be updated.

diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
index 76850ec9be..92f3b78f29 100644
--- a/arch/riscv/cpu/start.S
+++ b/arch/riscv/cpu/start.S
@@ -166,11 +166,22 @@ wait_for_gd_init:
mv  gp, s0
 
/* register available harts in the available_harts mask */
-   li  t1, 1
-   sll t1, t1, tp
-   LREGt2, GD_AVAILABLE_HARTS(gp)
-   or  t2, t2, t1
-   SREGt2, GD_AVAILABLE_HARTS(gp)
+   li  t1, GD_AVAILABLE_HARTS
+   add t1, t1, gp
+#if defined(CONFIG_ARCH_RV64I)
+   srlit2, tp, 6
+   sllit2, t2, 3
+#elif defined(CONFIG_ARCH_RV32I)
+   srlit2, tp, 5
+   sllit2, t2, 2
+#endif
+   add t1, t1, t2
+   LREGt2, 0(t1)
+   li  t3, 1
+   sll t3, t3, tp
+   or  t2, t2, t3
+   SREGt2, 0(t1)
 
amoswap.w.rl zero, zero, 0(t0)

The mailing list cannot receive my mail, please help to update



[PATCH] virtio: pci: fix bug of virtio_pci_map_capability

2022-08-28 Thread Xiang W
The bar of the structure virtio_pci_cap is the index, and each base
address occupies 4 bytes, so it needs to be multiplied by 4.

This patch fixes a bug reported by Felix Yan
https://lists.denx.de/pipermail/u-boot/2022-August/492779.html

Signed-off-by: Xiang W 
Tested-by: Felix Yan 
---
 drivers/virtio/virtio_pci_modern.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/virtio/virtio_pci_modern.c 
b/drivers/virtio/virtio_pci_modern.c
index 880a12cc28..cfde4007f5 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -466,7 +466,7 @@ static void __iomem *virtio_pci_map_capability(struct 
udevice *udev,
unsigned long mask =
PCI_REGION_TYPE | PCI_REGION_SYS_MEMORY | PCI_REGION_RO;
unsigned long flags = PCI_REGION_MEM;
-   u8 *p = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0 + cap->bar, cap->offset,
+   u8 *p = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0 + 4 * cap->bar, 
cap->offset,
   cap->length, mask, flags);
 
return (void __iomem *)p;
-- 
2.30.2



Re: [PATCH v2 18/18] virtio: pci: Make use of dm_pci_map_bar()

2022-08-28 Thread Xiang W
在 2022-08-25星期四的 11:01 +0300,Felix Yan写道:
> Hi,
> 
> Today I discovered a failure which bisected to this commit.
> 
> When running QEMU with libvirt, which created some pcie devices, U-boot 
> fails on autoboot with:
> 
> Unhandled exception: Load access fault
> EPC: bff7c46e RA: bff7c46c TVAL: 40200014
> EPC: 8002446e RA: 8002446c reloc adjusted
> 
> Code: 8082 1141 e022 e406 842e 40ef dc5f 611c (c783 0147)
> 
> I have tried to minimize the command line that makes the difference.
> 
> This works:
> 
> -device 
> '{"driver":"virtio-blk-pci","drive":"libvirt-2-format","id":"virtio-disk0","bootindex":1}'
> 
> This doesn't work:
> 
> -device 
> '{"driver":"virtio-blk-pci","bus":"pci.2","addr":"0x0","drive":"libvirt-2-format","id":"virtio-disk0","bootindex":1}'
> 
> I have tried this on multiple machines, different U-boot tags, mmode or 
> smode with OpenSBI, all with the same behavior. Latest U-boot master 
> with this commit reverted works fine on both cases.
> 
> I am very new to U-boot, please do let me know if more info are to be 
> provided.
> 
> Attached the full command line, for reference:
> 
> /usr/bin/qemu-system-riscv64  \
> -machine virt  \
> -bios u-boot/u-boot.bin  \
> -m 1024  \
> -device 
> '{"driver":"pcie-root-port","port":8,"chassis":1,"id":"pci.1","bus":"pcie.0","multifunction":true,"addr":"0x1"}'
>  
>   \
> -device 
> '{"driver":"pcie-root-port","port":9,"chassis":2,"id":"pci.2","bus":"pcie.0","addr":"0x1.0x1"}'
>  
>   \
> -blockdev 
> '{"driver":"file","filename":"archriscv-2022-08-24.qcow2","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}'
>  
>   \
> -blockdev 
> '{"node-name":"libvirt-2-format","read-only":false,"driver":"qcow2","file":"libvirt-2-storage","backing":null}'
>  
>   \
> -device 
> '{"driver":"virtio-blk-pci","bus":"pci.2","addr":"0x0","drive":"libvirt-2-format","id":"virtio-disk0","bootindex":1}'
>  
>   \
> -nographic
> 
> -- 
> Regards,
> Felix Yan

Please try my patch and let me know the test results

diff --git a/drivers/virtio/virtio_pci_modern.c 
b/drivers/virtio/virtio_pci_modern.c
index 880a12cc28..cfde4007f5 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -466,7 +466,7 @@ static void __iomem *virtio_pci_map_capability(struct 
udevice *udev,
unsigned long mask =
PCI_REGION_TYPE | PCI_REGION_SYS_MEMORY | PCI_REGION_RO;
unsigned long flags = PCI_REGION_MEM;
-   u8 *p = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0 + cap->bar, cap->offset,
+   u8 *p = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0 + 4 * cap->bar, 
cap->offset,
   cap->length, mask, flags);
 
return (void __iomem *)p;

Regards,
Xiang W



Re: [PATCH v2] riscv: cancel the limitation that NR_CPUS is less than or equal to 32

2021-12-29 Thread Xiang W
在 2021-12-29星期三的 17:23 +0800,Leo Liang写道:
> Hi Xiang,
> On Wed, Dec 22, 2021 at 07:32:53AM +0800, Xiang W wrote:
> > Various specifications of riscv allow the number of hart to be
> > greater than 32. The limit of 32 is determined by
> > gd->arch.available_harts. We can eliminate this limitation through
> > bitmaps. Currently, the number of hart is limited to 4095, and 4095
> > is the limit of the RISC-V Advanced Core Local Interruptor
> > Specification.
> > 
> > Test on sifive unmatched.
> > 
> > Signed-off-by: Xiang W 
> > ---
> > Changes since v1:
> > 
> > * When NR_CPUS is very large, the value of GD_AVAILABLE_HARTS will
> >   overflow the immediate range of ld/lw. This patch fixes this
> >   problem
> > 
> >  arch/riscv/Kconfig   |  4 ++--
> >  arch/riscv/cpu/start.S   | 21 -
> >  arch/riscv/include/asm/global_data.h |  4 +++-
> >  arch/riscv/lib/smp.c |  2 +-
> >  4 files changed, 22 insertions(+), 9 deletions(-)
> > 
> > diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
> > index 76850ec9be..92f3b78f29 100644
> > --- a/arch/riscv/cpu/start.S
> > +++ b/arch/riscv/cpu/start.S
> > @@ -166,11 +166,22 @@ wait_for_gd_init:
> > mv  gp, s0
> >  
> > /* register available harts in the available_harts mask */
> > -   li  t1, 1
> > -   sll t1, t1, tp
> > -   LREGt2, GD_AVAILABLE_HARTS(gp)
> > -   or  t2, t2, t1
> > -   SREGt2, GD_AVAILABLE_HARTS(gp)
> > +   li  t1, GD_AVAILABLE_HARTS
> > +   add t1, t1, gp
> > +   LREGt1, 0(t1)
> > +#if defined(CONFIG_ARCH_RV64I)
> > +   srlit2, tp, 6
> > +   sllit2, t2, 3
> > +#elif defined(CONFIG_ARCH_RV32I)
> > +   srlit2, tp, 5
> > +   sllit2, t2, 2
> > +#endif
> > +   add t1, t1, t2
> > +   LREGt2, 0(t1)
> > +   li  t3, 1
> > +   sll t3, t3, tp
> This seems incorrect.
> Shouldn't we have "$tp % sizeof(ulong)" instead of "$tp /
> sizeof(ulong)" ?

Do you meening: "$tp % sizeof(ulong)" instead of "$tp" ?

There is such a description in the riscv specification:

SLL, SRL, and SRA perform logical left, logical right, and arithmetic
right shifts on the value in register rs1 by the shift amount held in
the lower 5 bits of register rs2.

SLL, SRL, and SRA perform logical left, logical right, and arithmetic
right shifts on the value in register rs1 by the shift amount held in
register rs2. In RV64I, only the low 6 bits of rs2 are considered for
the shift amount.

So we don’t need to perform the remainder operation.

regards,
Xiang W
> > +   or  t2, t2, t3
> > +   SREGt2, 0(t1)
> >  
> > amoswap.w.rl zero, zero, 0(t0)
> Best regards,
> Leo




[PATCH v2] riscv: cancel the limitation that NR_CPUS is less than or equal to 32

2021-12-22 Thread Xiang W
Various specifications of riscv allow the number of hart to be
greater than 32. The limit of 32 is determined by
gd->arch.available_harts. We can eliminate this limitation through
bitmaps. Currently, the number of hart is limited to 4095, and 4095
is the limit of the RISC-V Advanced Core Local Interruptor
Specification.

Test on sifive unmatched.

Signed-off-by: Xiang W 
---
Changes since v1:

* When NR_CPUS is very large, the value of GD_AVAILABLE_HARTS will
  overflow the immediate range of ld/lw. This patch fixes this
  problem

 arch/riscv/Kconfig   |  4 ++--
 arch/riscv/cpu/start.S   | 21 -
 arch/riscv/include/asm/global_data.h |  4 +++-
 arch/riscv/lib/smp.c |  2 +-
 4 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index ba29e70acf..7b9c7f5bca 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -220,8 +220,8 @@ config SPL_SMP
  all, single processor machines.
 
 config NR_CPUS
-   int "Maximum number of CPUs (2-32)"
-   range 2 32
+   int "Maximum number of CPUs (2-4095)"
+   range 2 4095
depends on SMP || SPL_SMP
default 8
help
diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
index 76850ec9be..92f3b78f29 100644
--- a/arch/riscv/cpu/start.S
+++ b/arch/riscv/cpu/start.S
@@ -166,11 +166,22 @@ wait_for_gd_init:
mv  gp, s0
 
/* register available harts in the available_harts mask */
-   li  t1, 1
-   sll t1, t1, tp
-   LREGt2, GD_AVAILABLE_HARTS(gp)
-   or  t2, t2, t1
-   SREGt2, GD_AVAILABLE_HARTS(gp)
+   li  t1, GD_AVAILABLE_HARTS
+   add t1, t1, gp
+   LREGt1, 0(t1)
+#if defined(CONFIG_ARCH_RV64I)
+   srlit2, tp, 6
+   sllit2, t2, 3
+#elif defined(CONFIG_ARCH_RV32I)
+   srlit2, tp, 5
+   sllit2, t2, 2
+#endif
+   add t1, t1, t2
+   LREGt2, 0(t1)
+   li  t3, 1
+   sll t3, t3, tp
+   or  t2, t2, t3
+   SREGt2, 0(t1)
 
amoswap.w.rl zero, zero, 0(t0)
 
diff --git a/arch/riscv/include/asm/global_data.h 
b/arch/riscv/include/asm/global_data.h
index 095484a635..6de2ee0b25 100644
--- a/arch/riscv/include/asm/global_data.h
+++ b/arch/riscv/include/asm/global_data.h
@@ -10,9 +10,11 @@
 #ifndef__ASM_GBL_DATA_H
 #define __ASM_GBL_DATA_H
 
+#include 
 #include 
 #include 
 #include 
+#include 
 
 /* Architecture-specific global data */
 struct arch_global_data {
@@ -28,7 +30,7 @@ struct arch_global_data {
struct ipi_data ipi[CONFIG_NR_CPUS];
 #endif
 #ifndef CONFIG_XIP
-   ulong available_harts;
+   ulong available_harts[BITS_TO_LONGS(CONFIG_NR_CPUS)];
 #endif
 };
 
diff --git a/arch/riscv/lib/smp.c b/arch/riscv/lib/smp.c
index ba992100ad..e8e391fd41 100644
--- a/arch/riscv/lib/smp.c
+++ b/arch/riscv/lib/smp.c
@@ -47,7 +47,7 @@ static int send_ipi_many(struct ipi_data *ipi, int wait)
 
 #ifndef CONFIG_XIP
/* skip if hart is not available */
-   if (!(gd->arch.available_harts & (1 << reg)))
+   if (!test_bit(reg, gd->arch.available_harts))
continue;
 #endif
 
-- 
2.30.2



[PATCH] riscv: cancel the limitation that NR_CPUS is less than or equal to 32

2021-12-22 Thread Xiang W
Various specifications of riscv allow the number of hart to be
greater than 32. The limit of 32 is determined by
gd->arch.available_harts. We can eliminate this limitation through
bitmaps. Currently, the number of hart is limited to 4095, and 4095
is the limit of the RISC-V Advanced Core Local Interruptor
Specification.

Test on sifive unmatched.

Signed-off-by: Xiang W 
---
 arch/riscv/Kconfig   |  4 ++--
 arch/riscv/cpu/start.S   | 19 ++-
 arch/riscv/include/asm/global_data.h |  4 +++-
 arch/riscv/lib/smp.c |  2 +-
 4 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index ba29e70acf..7b9c7f5bca 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -220,8 +220,8 @@ config SPL_SMP
  all, single processor machines.
 
 config NR_CPUS
-   int "Maximum number of CPUs (2-32)"
-   range 2 32
+   int "Maximum number of CPUs (2-4095)"
+   range 2 4095
depends on SMP || SPL_SMP
default 8
help
diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
index 76850ec9be..1f97240713 100644
--- a/arch/riscv/cpu/start.S
+++ b/arch/riscv/cpu/start.S
@@ -166,11 +166,20 @@ wait_for_gd_init:
mv  gp, s0
 
/* register available harts in the available_harts mask */
-   li  t1, 1
-   sll t1, t1, tp
-   LREGt2, GD_AVAILABLE_HARTS(gp)
-   or  t2, t2, t1
-   SREGt2, GD_AVAILABLE_HARTS(gp)
+   LREGt1, GD_AVAILABLE_HARTS(gp)
+#if defined(CONFIG_ARCH_RV64I)
+   srlit2, tp, 6
+   sllit2, t2, 3
+#elif defined(CONFIG_ARCH_RV32I)
+   srlit2, tp, 5
+   sllit2, t2, 2
+#endif
+   add t1, t1, t2
+   LREGt2, 0(t1)
+   li  t3, 1
+   sll t3, t3, tp
+   or  t2, t2, t3
+   SREGt2, 0(t1)
 
amoswap.w.rl zero, zero, 0(t0)
 
diff --git a/arch/riscv/include/asm/global_data.h 
b/arch/riscv/include/asm/global_data.h
index 095484a635..6de2ee0b25 100644
--- a/arch/riscv/include/asm/global_data.h
+++ b/arch/riscv/include/asm/global_data.h
@@ -10,9 +10,11 @@
 #ifndef__ASM_GBL_DATA_H
 #define __ASM_GBL_DATA_H
 
+#include 
 #include 
 #include 
 #include 
+#include 
 
 /* Architecture-specific global data */
 struct arch_global_data {
@@ -28,7 +30,7 @@ struct arch_global_data {
struct ipi_data ipi[CONFIG_NR_CPUS];
 #endif
 #ifndef CONFIG_XIP
-   ulong available_harts;
+   ulong available_harts[BITS_TO_LONGS(CONFIG_NR_CPUS)];
 #endif
 };
 
diff --git a/arch/riscv/lib/smp.c b/arch/riscv/lib/smp.c
index ba992100ad..e8e391fd41 100644
--- a/arch/riscv/lib/smp.c
+++ b/arch/riscv/lib/smp.c
@@ -47,7 +47,7 @@ static int send_ipi_many(struct ipi_data *ipi, int wait)
 
 #ifndef CONFIG_XIP
/* skip if hart is not available */
-   if (!(gd->arch.available_harts & (1 << reg)))
+   if (!test_bit(reg, gd->arch.available_harts))
continue;
 #endif
 
-- 
2.30.2