Re: [RFC PATCH 0/6] Support raw event and DT for perf on RISC-V

2020-06-30 Thread Alan Kao
Tue, Jun 30, 2020 at 06:02:43PM -0700, Atish Patra wrote:
> On Tue, Jun 30, 2020 at 5:52 PM Alan Kao  wrote:
> >
> > On Mon, Jun 29, 2020 at 11:19:09AM +0800, Zong Li wrote:
> > > This patch set adds raw event support on RISC-V. In addition, we
> > > introduce the DT mechanism to make our perf more generic and common.
> > >
> > > Currently, we set the hardware events by writing the mhpmeventN CSRs, it
> > > would raise an illegal instruction exception and trap into m-mode to
> > > emulate event selector CSRs access. It doesn't make sense because we
> > > shouldn't write the m-mode CSRs in s-mode. Ideally, we should set event
> > > selector through standard SBI call or the shadow CSRs of s-mode. We have
> > > prepared a proposal of a new SBI extension, called "PMU SBI extension",
> > > but we also discussing the feasibility of accessing these PMU CSRs on
> > > s-mode at the same time, such as delegation mechanism, so I was
> > > wondering if we could use SBI calls first and make the PMU SBI extension
> > > as legacy when s-mode access mechanism is accepted by Foundation? or
> > > keep the current situation to see what would happen in the future.
> > >
> > > This patch set also introduces the DT mechanism, we don't want to add too
> > > much platform-dependency code in perf like other architectures, so we
> > > put the mapping of generic hardware events to DT, then we can easy to
> > > transfer generic hardware events to vendor's own hardware events without
> > > any platfrom-dependency stuff in our perf.
> > >
> > > Zong Li (6):
> > >   dt-bindings: riscv: Add YAML documentation for PMU
> > >   riscv: dts: sifive: Add DT support for PMU
> > >   riscv: add definition of hpmcounter CSRs
> > >   riscv: perf: Add raw event support
> > >   riscv: perf: introduce DT mechanism
> > >   riscv: remove PMU menu of Kconfig
> > >
> >
> > DT-based PMU registration looks good to me. Together with Anup's feedback,
> > we can anticipate that the following items will be:
> >
> > - rewrite RISC-V PMU to a platform driver
> > - propose SBI PMU extention
> > - fixes: RV32 counter access, namings, etc.
> >
> > Yes, all are good directions towards better counting (`perf stat`) function.
> > But as the original author of RISC-V perf port, please allow me to address
> > the fundamental problems of RISC-V perf, again [0][1][2][3], that the 
> > sampling
> > (`perf record`) function never earned enough respect.  Counting gives you a
> > shallow view regarding an application, while sampling demystifies one for 
> > you.
> >
> > The problems are three-fold
> > (1) Interrupt
> > Sampling in perf requires that a HPM raises an interrupt when it overflows.
> > Making RISC-V perf platform driver or not has nothing to do with this.  This
> > requires more discussions in TGs.
> > (2) S-mode access to PMU CSRs
> > This is also addressed in this patch set but to me, it is kind of like a
> > SBI-solves-them-all mindset to me.  Perf event is for performance monitoring
> > thus we should eliminate any possible overhead if we can.  Setting event 
> > masks
> > through SBI calls for counting maybe OK, but if we really take sampling and
> > interrupt handling into consideration, it is questionable if it is still a
> > viable way.
> > (3) Registers, registers, registers
> > There is just no enough CSR/function for perf sampling. The previous 
> > proposal
> > explains why [2].
> >
> > Perf sampling is off-topic but somehow related, so I bring it up here just
> > for your information.
> >
> > As this patch set goes v2, the PMU porting guide in [0] should be removed 
> > since
> > it contains no useful information anymore.
> >
> > [0] Documentation/riscv/pmu.rst
> > [1] https://www.youtube.com/watch?v=Onvlcl4e2IU
> > [2] https://github.com/riscv/riscv-isa-manual/issues/402
> > This proposal has been posted in Privileged Spec Task Group, in
> > https://lists.riscv.org/g/tech-privileged-archive/message/488?p=,,,20,0,0,0::Created,,Proposal,20,2,40,32306071
> > but never receive any feedback.
> > [3] https://lists.riscv.org/g/tech-unixplatformspec/message/84
> > I intended to discuss [2] in the Unixplatform Spec Task Group at the
> > online meeting, but obviously people were too busy knowing who the new
> > RISC-V CTO is and what he has done to even follow the agenda.
> >
> 
> Sorry. The last meeting's agenda was derailed for numerous reasons.

Re: [RFC PATCH 0/6] Support raw event and DT for perf on RISC-V

2020-06-30 Thread Alan Kao
On Mon, Jun 29, 2020 at 11:19:09AM +0800, Zong Li wrote:
> This patch set adds raw event support on RISC-V. In addition, we
> introduce the DT mechanism to make our perf more generic and common.
> 
> Currently, we set the hardware events by writing the mhpmeventN CSRs, it
> would raise an illegal instruction exception and trap into m-mode to
> emulate event selector CSRs access. It doesn't make sense because we
> shouldn't write the m-mode CSRs in s-mode. Ideally, we should set event
> selector through standard SBI call or the shadow CSRs of s-mode. We have
> prepared a proposal of a new SBI extension, called "PMU SBI extension",
> but we also discussing the feasibility of accessing these PMU CSRs on
> s-mode at the same time, such as delegation mechanism, so I was
> wondering if we could use SBI calls first and make the PMU SBI extension
> as legacy when s-mode access mechanism is accepted by Foundation? or
> keep the current situation to see what would happen in the future.
> 
> This patch set also introduces the DT mechanism, we don't want to add too
> much platform-dependency code in perf like other architectures, so we
> put the mapping of generic hardware events to DT, then we can easy to
> transfer generic hardware events to vendor's own hardware events without
> any platfrom-dependency stuff in our perf.
> 
> Zong Li (6):
>   dt-bindings: riscv: Add YAML documentation for PMU
>   riscv: dts: sifive: Add DT support for PMU
>   riscv: add definition of hpmcounter CSRs
>   riscv: perf: Add raw event support
>   riscv: perf: introduce DT mechanism
>   riscv: remove PMU menu of Kconfig
> 

DT-based PMU registration looks good to me. Together with Anup's feedback,
we can anticipate that the following items will be:

- rewrite RISC-V PMU to a platform driver
- propose SBI PMU extention
- fixes: RV32 counter access, namings, etc.

Yes, all are good directions towards better counting (`perf stat`) function.
But as the original author of RISC-V perf port, please allow me to address
the fundamental problems of RISC-V perf, again [0][1][2][3], that the sampling
(`perf record`) function never earned enough respect.  Counting gives you a
shallow view regarding an application, while sampling demystifies one for you.

The problems are three-fold
(1) Interrupt
Sampling in perf requires that a HPM raises an interrupt when it overflows.
Making RISC-V perf platform driver or not has nothing to do with this.  This
requires more discussions in TGs.
(2) S-mode access to PMU CSRs
This is also addressed in this patch set but to me, it is kind of like a
SBI-solves-them-all mindset to me.  Perf event is for performance monitoring
thus we should eliminate any possible overhead if we can.  Setting event masks
through SBI calls for counting maybe OK, but if we really take sampling and
interrupt handling into consideration, it is questionable if it is still a
viable way.
(3) Registers, registers, registers
There is just no enough CSR/function for perf sampling. The previous proposal
explains why [2].

Perf sampling is off-topic but somehow related, so I bring it up here just
for your information.

As this patch set goes v2, the PMU porting guide in [0] should be removed since
it contains no useful information anymore.

[0] Documentation/riscv/pmu.rst
[1] https://www.youtube.com/watch?v=Onvlcl4e2IU
[2] https://github.com/riscv/riscv-isa-manual/issues/402
This proposal has been posted in Privileged Spec Task Group, in
https://lists.riscv.org/g/tech-privileged-archive/message/488?p=,,,20,0,0,0::Created,,Proposal,20,2,40,32306071
but never receive any feedback.
[3] https://lists.riscv.org/g/tech-unixplatformspec/message/84
I intended to discuss [2] in the Unixplatform Spec Task Group at the
online meeting, but obviously people were too busy knowing who the new
RISC-V CTO is and what he has done to even follow the agenda.



Re: [v6 PATCH] RISC-V: Remove unsupported isa string info print

2019-10-01 Thread Alan Kao
On Tue, Oct 01, 2019 at 03:10:16AM -0700, h...@infradead.org wrote:
> On Tue, Oct 01, 2019 at 08:22:37AM +, Atish Patra wrote:
> > riscv_of_processor_hartid() or seems to be a better candidate. We
> > already check if "rv" is present in isa string or not. I will extend
> > that to check for rv64i or rv32i. Is that okay ?
> 
> I'd rather lift the checks out of that into a function that is called
> exactly once per hart on boot (and future cpu hotplug).

Sorry that I am a bit out of date on this.  Is there any related
discussion about such checks?  Just want to make sure if the check
stops here and will not go any further for extensions, Xs and Zs.

> 
> ___
> linux-riscv mailing list
> linux-ri...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv


Re: [PATCH v2 0/3] Add support for SBI v0.2

2019-09-30 Thread Alan Kao
On Fri, Sep 27, 2019 at 10:57:45PM +, Atish Patra wrote:
> On Fri, 2019-09-27 at 15:19 -0700, Christoph Hellwig wrote:
> > On Thu, Sep 26, 2019 at 05:09:12PM -0700, Atish Patra wrote:
> > > The Supervisor Binary Interface(SBI) specification[1] now defines a
> > > base extension that provides extendability to add future extensions
> > > while maintaining backward compatibility with previous versions.
> > > The new version is defined as 0.2 and older version is marked as
> > > 0.1.
> > > 
> > > This series adds support v0.2 and a unified calling convention
> > > implementation between 0.1 and 0.2. It also adds minimal SBI
> > > functions
> > > from 0.2 as well to keep the series lean. 
> > 
> > So before we do this game can be please make sure we have a clean 0.2
> > environment that never uses the legacy extensions as discussed
> > before?
> > Without that all this work is rather futile.
> > 
> 
> As per our discussion offline, here are things need to be done to
> achieve that.
> 
> 1. Replace timer, sfence and ipi with better alternative APIs
>   - sbi_set_timer will be same but with new calling convention
>   - send_ipi and sfence_* apis can be modified in such a way that
>   - we don't have to use unprivileged load anymore
>   - Make it scalable
> 
> 2. Drop clear_ipi, console, and shutdown in 0.2.
> 
> We will have a new kernel config (LEGACY_SBI) that can be manually
> enabled if older firmware need to be used. By default, LEGACY_SBI will
> be disabled and kernel with new SBI will be built. We will have to set
> a flag day in a year or so when we can remove the LEGACY_SBI
> completely.
> 
> Let us know if it is not an acceptable approach to anybody.
> I will post a RFC patch with new alternate v0.2 APIs sometime next
> week.
>

Will this legacy option be compatible will bbl?  says, version 1.0.0 or
any earlier ones?

> > ___
> > linux-riscv mailing list
> > linux-ri...@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-riscv
> 
> -- 
> Regards,
> Atish


Re: [PATCH 08/15] riscv: provide native clint access for M-mode

2019-09-03 Thread Alan Kao
On Tue, Sep 03, 2019 at 11:48:52AM -0700, Palmer Dabbelt wrote:
> On Tue, 27 Aug 2019 23:11:46 PDT (-0700), Christoph Hellwig wrote:
> >On Tue, Aug 27, 2019 at 04:37:16PM -0700, Palmer Dabbelt wrote:
> >>clint0 would be version 0 of the clint, with is the core-local interrupt
> >>controller in rocket chip.  It should be "sifive,clint-1.0.0", not
> >>"riscv,clint0", as it's a SiFive widget.  Unfortunately there are a lot of
> >>legacy device trees floating around, but I'm only considering what's been
> >>upstream to be actually part of the spec.
> >>
> >>In this case the code should match on a "sifive,clint-1.0.0", and the
> >>device trees should be fixed up to match.  We match on "riscv,plic0" for
> >>legacy systems, and I guess it makes sense to do something similar here.
> >
> >IFF we decided to change it I'd rather separate DT noes for the ipi
> >bank vs timecmp register vs timeval to support variable layouts.  The
> >downside is that we can't just boot on unmodified upstream qemu, which
> >has used the "riscv,clint0" for years.
> 
> Like I alluded to above, matching on "riscv,clint0" seems reasonable to me
> as it's a defacto standard -- we'll just have to make sure that if we ever
> end up with a RISC-V CLINT that the DT entry is something else.

De facto, but not mandatory.

> 
> As far as splitting the memory maps goes, I don't have a strong opinion but
> it seems like that'll introduce more complexity than it's worth.
> 

At least the splitting can keep reminding us and any new comers in the future
that CLINT is not (yet) a must in RISC-V landscape.  A previous discussion
FYI: ( https://lkml.org/lkml/2019/8/20/1361 )

> ___
> linux-riscv mailing list
> linux-ri...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv


Re: [v2 PATCH] RISC-V: Optimize tlb flush path.

2019-08-20 Thread Alan Kao
On Tue, Aug 20, 2019 at 08:28:36PM +, Atish Patra wrote:
> On Tue, 2019-08-20 at 02:22 -0700, h...@infradead.org wrote:
> > On Tue, Aug 20, 2019 at 08:42:19AM +, Atish Patra wrote:
> > > cmask NULL is pretty common case and we would  be unnecessarily
> > > executing bunch of instructions everytime while not saving much.
> > > Kernel
> > > still have to make an SBI call and OpenSBI is doing a local flush
> > > anyways.
> > > 
> > > Looking at the code again, I think we can just use cpumask_weight
> > > and
> > > do local tlb flush only if local cpu is the only cpu present. 
> > > 
> > > Otherwise, it will just fall through and call
> > > sbi_remote_sfence_vma().
> > 
> > Maybe it is just time to split the different cases at a higher level.
> > The idea to multiple everything onto a single function always seemed
> > odd to me.
> > 
> > FYI, here is what I do for the IPI based tlbflush for the native S-
> > mode
> > clint prototype, which seems much easier to understand:
> > 
> > http://git.infradead.org/users/hch/riscv.git/commitdiff/ea4067ae61e20fcfcf46a6f6bd1cc25710ce3afe
> 
> This does seem a lot cleaner to me. We can reuse some of the code for
> this patch as well. Based on NATIVE_CLINT configuration, it will send
> an IPI or SBI call.

IMHO, this approach should be avoided because CLINT is compatible to but
 not mandatory in the privileged spec.  In other words, it is possible that
a Linux-capable RISC-V platform does not contain a CLINT component but
rely on some other mechanism to deal with SW/timer interrupts.

> 
> I can rebase my patch on top of yours and I can send it together or you
> can include in your series.
> 
> Let me know your preference.
> 
> -- 
> Regards,
> Atish

Best,
Alan


Re: [PATCH 13/15] riscv: clear the instruction cache and all registers when booting

2019-08-13 Thread Alan Kao
Hi Christoph,

On Tue, Aug 13, 2019 at 05:47:45PM +0200, Christoph Hellwig wrote:
> When we get booted we want a clear slate without any leaks from previous
> supervisors or the firmware.  Flush the instruction cache and then clear
> all registers to known good values.  This is really important for the
> upcoming nommu support that runs on M-mode, but can't really harm when
> running in S-mode either.  

Sure.

> +#ifdef CONFIG_FPU

But it doesn't really mean that the running system has an FPU given CONFIG_FPU
enabled.  Normally the existence of an FPU is checked in riscv_fill_hwcap by
searching device tree, where the code looks like


bool has_fpu = false; // this one is global
...
#ifdef CONFIG_FPU
if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
has_fpu = true;
#endif


Or does CONFIG_FPU have a more intuitive meaning when CONFIG_M_MODE is enabled?

> + csrrt0, CSR_MISA
> + andit0, t0, (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D)
> + bnezt0, .Lreset_regs_done
> +
> + li  t1, SR_FS
> + csrsCSR_XSTATUS, t1
> + fmv.s.x f0, zero
> + fmv.s.x f1, zero
> + fmv.s.x f2, zero
> + fmv.s.x f3, zero
> + fmv.s.x f4, zero
> + fmv.s.x f5, zero
> + fmv.s.x f6, zero
> + fmv.s.x f7, zero
> + fmv.s.x f8, zero
> + fmv.s.x f9, zero
> + fmv.s.x f10, zero
> + fmv.s.x f11, zero
> + fmv.s.x f12, zero
> + fmv.s.x f13, zero
> + fmv.s.x f14, zero
> + fmv.s.x f15, zero
> + fmv.s.x f16, zero
> + fmv.s.x f17, zero
> + fmv.s.x f18, zero
> + fmv.s.x f19, zero
> + fmv.s.x f20, zero
> + fmv.s.x f21, zero
> + fmv.s.x f22, zero
> + fmv.s.x f23, zero
> + fmv.s.x f24, zero
> + fmv.s.x f25, zero
> + fmv.s.x f26, zero
> + fmv.s.x f27, zero
> + fmv.s.x f28, zero
> + fmv.s.x f29, zero
> + fmv.s.x f30, zero
> + fmv.s.x f31, zero
> + csrwfcsr, 0
> + /* note that the caller must clear SR_FS */
> +#endif /* CONFIG_FPU */


Re: [PATCH 13/15] riscv: clear the instruction cache and all registers when booting

2019-08-13 Thread Alan Kao


Please ignore the previous mail, I must have missed this part of the patch,
> 
> > +   csrrt0, CSR_MISA
> > +   andit0, t0, (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D)
> > +   bnezt0, .Lreset_regs_done
> > +

In S-mode we were not able to obtain the ISA information in misa, but now
the nommu port is in M-mode so this is rather straightforward.



Re: [PATCH v2] RISC-V: Always compile mm/init.c with cmodel=medany

2019-03-24 Thread Alan Kao
Hi Anup,

Sorry for being late to the party.  I think one more thing should
move together with setup_vm():

On Mon, Mar 25, 2019 at 03:37:38AM +, Anup Patel wrote:
> The Linux RISC-V 32bit kernel is broken after we moved setup_vm() from
> kernel/setup.c to mm/init.c because Linux RISC-V 32bit kernel by default
> uses cmodel=medlow which results in a non-position-independent setup_vm().
> 
> This patch fixes Linux RISC-V 32bit kernel booting by:
> 1. Forcing cmodel=medany for mm/init.c
> 2. Moving remaing MM-related stuff va_pa_offset, pfn_base and
>empty_zero_page from kernel/setup.c to mm/init.c
> 
> Fixes: 6f1e9e946f0b ("RISC-V: Move setup_vm() to mm/init.c")
> Suggested-by: Christoph Hellwig 
> Suggested-by: Mike Rapoport 
> Signed-off-by: Anup Patel 
> ---
> v2: Removed CFLAGS_setup.o from kernel/Makefile and replaced SoBs
> ---
>  arch/riscv/kernel/Makefile | 2 --
>  arch/riscv/kernel/setup.c  | 8 
>  arch/riscv/mm/Makefile | 2 ++
>  arch/riscv/mm/init.c   | 9 +
>  4 files changed, 11 insertions(+), 10 deletions(-)
> 
> diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
> index f13f7f276639..8b9780b6bd7f 100644
> --- a/arch/riscv/kernel/Makefile
> +++ b/arch/riscv/kernel/Makefile

earlier in this file, there are four lines about ftrace,

  5 ifdef CONFIG_FTRACE
  6 CFLAGS_REMOVE_ftrace.o = -pg
  7 CFLAGS_REMOVE_setup.o = -pg
  8 endif

removing "-pg" flag from setup.o was necessary for ftrace to work, since
setup_vm() cannot process the trampoline of ftrace properly.

As setup_vm() is being moved to mm/init.c, you may either mark it with a
"notrace" attribute with its declaration, or adding corresponding CFLAGS_REMOVE*
to mm/Makefile.

> @@ -29,8 +29,6 @@ obj-y   += vdso.o
>  obj-y+= cacheinfo.o
>  obj-y+= vdso/
>  
> -CFLAGS_setup.o := -mcmodel=medany
> -
>  obj-$(CONFIG_FPU)+= fpu.o
>  obj-$(CONFIG_SMP)+= smpboot.o
>  obj-$(CONFIG_SMP)+= smp.o
> diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
> index ecb654f6a79e..540a331d1376 100644
> --- a/arch/riscv/kernel/setup.c
> +++ b/arch/riscv/kernel/setup.c
> @@ -48,14 +48,6 @@ struct screen_info screen_info = {
>  };
>  #endif
>  
> -unsigned long va_pa_offset;
> -EXPORT_SYMBOL(va_pa_offset);
> -unsigned long pfn_base;
> -EXPORT_SYMBOL(pfn_base);
> -
> -unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] 
> __page_aligned_bss;
> -EXPORT_SYMBOL(empty_zero_page);
> -
>  /* The lucky hart to first increment this variable will boot the other cores 
> */
>  atomic_t hart_lottery;
>  unsigned long boot_cpu_hartid;
> diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile
> index eb22ab49b3e0..7307609d405b 100644
> --- a/arch/riscv/mm/Makefile
> +++ b/arch/riscv/mm/Makefile
> @@ -3,3 +3,5 @@ obj-y += fault.o
>  obj-y += extable.o
>  obj-y += ioremap.o
>  obj-y += cacheflush.o
> +
> +CFLAGS_init.o := -mcmodel=medany
> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> index b379a75ac6a6..7a7c454378cb 100644
> --- a/arch/riscv/mm/init.c
> +++ b/arch/riscv/mm/init.c
> @@ -25,6 +25,10 @@
>  #include 
>  #include 
>  
> +unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]
> + __page_aligned_bss;
> +EXPORT_SYMBOL(empty_zero_page);
> +
>  static void __init zone_sizes_init(void)
>  {
>   unsigned long max_zone_pfns[MAX_NR_ZONES] = { 0, };
> @@ -143,6 +147,11 @@ void __init setup_bootmem(void)
>   }
>  }
>  
> +unsigned long va_pa_offset;
> +EXPORT_SYMBOL(va_pa_offset);
> +unsigned long pfn_base;
> +EXPORT_SYMBOL(pfn_base);
> +
>  pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
>  pgd_t trampoline_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);
>  
> -- 
> 2.17.1
> 
> 
> ___
> linux-riscv mailing list
> linux-ri...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv

Alan


[PATCH] riscv: fix accessing 8-byte variable from RV32

2019-03-22 Thread Alan Kao
A memory save operation to 8-byte variable in RV32 is divided into
two sw instructions in the put_user macro.  The current fixup returns
execution flow to the second sw instead of the one after it.

This patch fixes this fixup code according to the load access part.

Signed-off-by: Alan Kao
Cc: Greentime Hu 
Cc: Vincent Chen 
---
 arch/riscv/include/asm/uaccess.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/riscv/include/asm/uaccess.h b/arch/riscv/include/asm/uaccess.h
index a00168b..fb53a80 100644
--- a/arch/riscv/include/asm/uaccess.h
+++ b/arch/riscv/include/asm/uaccess.h
@@ -300,7 +300,7 @@ do {
\
"   .balign 4\n"\
"4:\n"  \
"   li %0, %6\n"\
-   "   jump 2b, %1\n"  \
+   "   jump 3b, %1\n"  \
"   .previous\n"\
"   .section __ex_table,\"a\"\n"\
"   .balign " RISCV_SZPTR "\n"  \
-- 
2.7.4



Re: [RFC 0/2] RISC-V: A proposal to add vendor-specific code

2018-11-01 Thread Alan Kao
On Thu, Nov 01, 2018 at 10:50:04AM -0700, Palmer Dabbelt wrote:
> On Wed, 31 Oct 2018 17:55:42 PDT (-0700), alan...@andestech.com wrote:
> >On Wed, Oct 31, 2018 at 07:17:45AM -0700, Christoph Hellwig wrote:
> >>On Wed, Oct 31, 2018 at 04:46:10PM +0530, Anup Patel wrote:
> >>> I agree that we need a place for vendor-specific ISA extensions and
> >>> having vendor-specific directories is also good.
> >>
> >>The only sensible answer is that we should not allow vendor specific
> >>extensions in the kernel at all.  ...
> >
> >How can this even be possible if a extension includes an extra register
> >set as some domain-specific context?  In such a case, kernel should
> >at least process the context during any context switch, just like how it
> >deals with the FP context.
> 
> Ya, I think there are cases where vendor-specific extensions are going to be
> necessary to handle within the kernel.  Right now the only one I can think
> of is the performance counter stuff, where we explicitly allow
> vendor-specific counters as part of the ISA spec.
> 
> For stateful extensions, we currently have a standard mechanism where the XS
> bits get set in sstatus and the actual save/restore code is hidden behind an
> SBI call.  That call doesn't currently exist, but if we just go ahead and
> add one it should be easy to support this from within Linux.  We'll need to
> figure out how to enable these custom extensions from userspace, but that
> seems tractable as well.  We'll probably also want some fast-path for the V
> extension (and any other stateful standard extensions), but I think as long
> as the V extension adds a quick check for dirtiness then it's not a big
> deal.
> 
> Do you guys have stateful extensions?  We're trying really hard to avoid
> them at SiFive because they're a huge headache, so unless there's a
> compelling base of software using one I don't want to go add support if we
> can avoid it.

Currently no, but the future is hard to see.  As long as the extensible freedom
claimed by the RISC-V foundation remains true, such extensions may have their
role to play.  Don't worry now, I was just to give a example that in some 
possible vendor-specific cases the kernel cannot keep itself from involving.



Re: [RFC 0/2] RISC-V: A proposal to add vendor-specific code

2018-11-01 Thread Alan Kao
On Thu, Nov 01, 2018 at 10:50:04AM -0700, Palmer Dabbelt wrote:
> On Wed, 31 Oct 2018 17:55:42 PDT (-0700), alan...@andestech.com wrote:
> >On Wed, Oct 31, 2018 at 07:17:45AM -0700, Christoph Hellwig wrote:
> >>On Wed, Oct 31, 2018 at 04:46:10PM +0530, Anup Patel wrote:
> >>> I agree that we need a place for vendor-specific ISA extensions and
> >>> having vendor-specific directories is also good.
> >>
> >>The only sensible answer is that we should not allow vendor specific
> >>extensions in the kernel at all.  ...
> >
> >How can this even be possible if a extension includes an extra register
> >set as some domain-specific context?  In such a case, kernel should
> >at least process the context during any context switch, just like how it
> >deals with the FP context.
> 
> Ya, I think there are cases where vendor-specific extensions are going to be
> necessary to handle within the kernel.  Right now the only one I can think
> of is the performance counter stuff, where we explicitly allow
> vendor-specific counters as part of the ISA spec.
> 
> For stateful extensions, we currently have a standard mechanism where the XS
> bits get set in sstatus and the actual save/restore code is hidden behind an
> SBI call.  That call doesn't currently exist, but if we just go ahead and
> add one it should be easy to support this from within Linux.  We'll need to
> figure out how to enable these custom extensions from userspace, but that
> seems tractable as well.  We'll probably also want some fast-path for the V
> extension (and any other stateful standard extensions), but I think as long
> as the V extension adds a quick check for dirtiness then it's not a big
> deal.
> 
> Do you guys have stateful extensions?  We're trying really hard to avoid
> them at SiFive because they're a huge headache, so unless there's a
> compelling base of software using one I don't want to go add support if we
> can avoid it.

Currently no, but the future is hard to see.  As long as the extensible freedom
claimed by the RISC-V foundation remains true, such extensions may have their
role to play.  Don't worry now, I was just to give a example that in some 
possible vendor-specific cases the kernel cannot keep itself from involving.



Re: [RFC 0/2] RISC-V: A proposal to add vendor-specific code

2018-10-31 Thread Alan Kao
On Wed, Oct 31, 2018 at 07:17:45AM -0700, Christoph Hellwig wrote:
> On Wed, Oct 31, 2018 at 04:46:10PM +0530, Anup Patel wrote:
> > I agree that we need a place for vendor-specific ISA extensions and
> > having vendor-specific directories is also good.
> 
> The only sensible answer is that we should not allow vendor specific
> extensions in the kernel at all.  ...

How can this even be possible if a extension includes an extra register
set as some domain-specific context?  In such a case, kernel should
at least process the context during any context switch, just like how it
deals with the FP context.

> ... We need to standardize cache flushing 
> and we need to do it soon and not introduce horrible bandaids because
> the foundation did not do its work.
> 
> ___
> linux-riscv mailing list
> linux-ri...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv


Re: [RFC 0/2] RISC-V: A proposal to add vendor-specific code

2018-10-31 Thread Alan Kao
On Wed, Oct 31, 2018 at 07:17:45AM -0700, Christoph Hellwig wrote:
> On Wed, Oct 31, 2018 at 04:46:10PM +0530, Anup Patel wrote:
> > I agree that we need a place for vendor-specific ISA extensions and
> > having vendor-specific directories is also good.
> 
> The only sensible answer is that we should not allow vendor specific
> extensions in the kernel at all.  ...

How can this even be possible if a extension includes an extra register
set as some domain-specific context?  In such a case, kernel should
at least process the context during any context switch, just like how it
deals with the FP context.

> ... We need to standardize cache flushing 
> and we need to do it soon and not introduce horrible bandaids because
> the foundation did not do its work.
> 
> ___
> linux-riscv mailing list
> linux-ri...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv


Re: [PATCH v8 3/5] Cleanup ISA string setting

2018-10-14 Thread Alan Kao
Hi Guenter,

On Sat, Oct 13, 2018 at 05:02:05PM -0700, Guenter Roeck wrote:
> Hi,
> 
> With this patch in -next applied, I get the following error
> when building riscv:defconfig.

I guess what you meant was this commit:
commit 0a5bee05fc67ce2044b8d91a18abbf14042da531

The modification in Makefile was

-endif
-
-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+# ISA string setting
+riscv-march-$(CONFIG_ARCH_RV32I)   := rv32im
+riscv-march-$(CONFIG_ARCH_RV64I)   := rv64im
+riscv-march-$(CONFIG_RISCV_ISA_A)  := $(riscv-march-y)a
+riscv-march-y  := fd
+riscv-march-$(CONFIG_RISCV_ISA_C)  := $(riscv-march-y)c

and the ":= fd" line was wrong.  It should have been 

+riscv-march-y  := $(riscv-march-y)fd

> 
> 
> What am I missing ? Does RISC-V now require a new non-upstream compiler ?
> Or a special version of make ? I am currently using GNU Make 4.1.

So I sent the v8 to fix this problem.
Sorry for the inconvinience.

> 
> Thanks,
> Guenter
> 
> ---

And Palmer, it seems that the patch that causes this build error has been
pulled into linux-next.  Any idea how to fix that one?

Many thanks,
Alan


Re: [PATCH v8 3/5] Cleanup ISA string setting

2018-10-14 Thread Alan Kao
Hi Guenter,

On Sat, Oct 13, 2018 at 05:02:05PM -0700, Guenter Roeck wrote:
> Hi,
> 
> With this patch in -next applied, I get the following error
> when building riscv:defconfig.

I guess what you meant was this commit:
commit 0a5bee05fc67ce2044b8d91a18abbf14042da531

The modification in Makefile was

-endif
-
-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+# ISA string setting
+riscv-march-$(CONFIG_ARCH_RV32I)   := rv32im
+riscv-march-$(CONFIG_ARCH_RV64I)   := rv64im
+riscv-march-$(CONFIG_RISCV_ISA_A)  := $(riscv-march-y)a
+riscv-march-y  := fd
+riscv-march-$(CONFIG_RISCV_ISA_C)  := $(riscv-march-y)c

and the ":= fd" line was wrong.  It should have been 

+riscv-march-y  := $(riscv-march-y)fd

> 
> 
> What am I missing ? Does RISC-V now require a new non-upstream compiler ?
> Or a special version of make ? I am currently using GNU Make 4.1.

So I sent the v8 to fix this problem.
Sorry for the inconvinience.

> 
> Thanks,
> Guenter
> 
> ---

And Palmer, it seems that the patch that causes this build error has been
pulled into linux-next.  Any idea how to fix that one?

Many thanks,
Alan


[PATCH v8 1/5] Extract FPU context operations from entry.S

2018-10-08 Thread Alan Kao
We move __fstate_save and __fstate_restore to a new source
file, fpu.S.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/entry.S  |  87 -
 arch/riscv/kernel/fpu.S| 106 +
 3 files changed, 107 insertions(+), 87 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index e1274fc..bd433efd 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,6 +13,7 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
+obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index fa2c08e..59c02e2 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -357,93 +357,6 @@ ENTRY(__switch_to)
ret
 ENDPROC(__switch_to)
 
-ENTRY(__fstate_save)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   csrs sstatus, t1
-   frcsr t0
-   fsd f0,  TASK_THREAD_F0_F0(a0)
-   fsd f1,  TASK_THREAD_F1_F0(a0)
-   fsd f2,  TASK_THREAD_F2_F0(a0)
-   fsd f3,  TASK_THREAD_F3_F0(a0)
-   fsd f4,  TASK_THREAD_F4_F0(a0)
-   fsd f5,  TASK_THREAD_F5_F0(a0)
-   fsd f6,  TASK_THREAD_F6_F0(a0)
-   fsd f7,  TASK_THREAD_F7_F0(a0)
-   fsd f8,  TASK_THREAD_F8_F0(a0)
-   fsd f9,  TASK_THREAD_F9_F0(a0)
-   fsd f10, TASK_THREAD_F10_F0(a0)
-   fsd f11, TASK_THREAD_F11_F0(a0)
-   fsd f12, TASK_THREAD_F12_F0(a0)
-   fsd f13, TASK_THREAD_F13_F0(a0)
-   fsd f14, TASK_THREAD_F14_F0(a0)
-   fsd f15, TASK_THREAD_F15_F0(a0)
-   fsd f16, TASK_THREAD_F16_F0(a0)
-   fsd f17, TASK_THREAD_F17_F0(a0)
-   fsd f18, TASK_THREAD_F18_F0(a0)
-   fsd f19, TASK_THREAD_F19_F0(a0)
-   fsd f20, TASK_THREAD_F20_F0(a0)
-   fsd f21, TASK_THREAD_F21_F0(a0)
-   fsd f22, TASK_THREAD_F22_F0(a0)
-   fsd f23, TASK_THREAD_F23_F0(a0)
-   fsd f24, TASK_THREAD_F24_F0(a0)
-   fsd f25, TASK_THREAD_F25_F0(a0)
-   fsd f26, TASK_THREAD_F26_F0(a0)
-   fsd f27, TASK_THREAD_F27_F0(a0)
-   fsd f28, TASK_THREAD_F28_F0(a0)
-   fsd f29, TASK_THREAD_F29_F0(a0)
-   fsd f30, TASK_THREAD_F30_F0(a0)
-   fsd f31, TASK_THREAD_F31_F0(a0)
-   sw t0, TASK_THREAD_FCSR_F0(a0)
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_save)
-
-ENTRY(__fstate_restore)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   lw t0, TASK_THREAD_FCSR_F0(a0)
-   csrs sstatus, t1
-   fld f0,  TASK_THREAD_F0_F0(a0)
-   fld f1,  TASK_THREAD_F1_F0(a0)
-   fld f2,  TASK_THREAD_F2_F0(a0)
-   fld f3,  TASK_THREAD_F3_F0(a0)
-   fld f4,  TASK_THREAD_F4_F0(a0)
-   fld f5,  TASK_THREAD_F5_F0(a0)
-   fld f6,  TASK_THREAD_F6_F0(a0)
-   fld f7,  TASK_THREAD_F7_F0(a0)
-   fld f8,  TASK_THREAD_F8_F0(a0)
-   fld f9,  TASK_THREAD_F9_F0(a0)
-   fld f10, TASK_THREAD_F10_F0(a0)
-   fld f11, TASK_THREAD_F11_F0(a0)
-   fld f12, TASK_THREAD_F12_F0(a0)
-   fld f13, TASK_THREAD_F13_F0(a0)
-   fld f14, TASK_THREAD_F14_F0(a0)
-   fld f15, TASK_THREAD_F15_F0(a0)
-   fld f16, TASK_THREAD_F16_F0(a0)
-   fld f17, TASK_THREAD_F17_F0(a0)
-   fld f18, TASK_THREAD_F18_F0(a0)
-   fld f19, TASK_THREAD_F19_F0(a0)
-   fld f20, TASK_THREAD_F20_F0(a0)
-   fld f21, TASK_THREAD_F21_F0(a0)
-   fld f22, TASK_THREAD_F22_F0(a0)
-   fld f23, TASK_THREAD_F23_F0(a0)
-   fld f24, TASK_THREAD_F24_F0(a0)
-   fld f25, TASK_THREAD_F25_F0(a0)
-   fld f26, TASK_THREAD_F26_F0(a0)
-   fld f27, TASK_THREAD_F27_F0(a0)
-   fld f28, TASK_THREAD_F28_F0(a0)
-   fld f29, TASK_THREAD_F29_F0(a0)
-   fld f30, TASK_THREAD_F30_F0(a0)
-   fld f31, TASK_THREAD_F31_F0(a0)
-   fscsr t0
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_restore)
-
-
.section ".rodata"
/* Exception vector table */
 ENTRY(excp_vect_table)
diff --git a/arch/riscv/kernel/fpu.S b/arch/riscv/kernel/fpu.S
new file mode 100644
index 000..1defb06
--- /dev/null
+++ b/arch/riscv/kernel/fpu.S
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2012 Regents of the University of California
+ * Copyright (C) 2017 SiFive
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include 
+
+#include 

[PATCH v8 3/5] Cleanup ISA string setting

2018-10-08 Thread Alan Kao
This patch cleanup the MARCH string passing to both compiler and
assembler.  Note that the CFLAGS should not contain "fd" before we
have mechnisms like kernel_fpu_begin/end in other architectures.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/Makefile | 19 ---
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 61ec424..01393e1 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -28,7 +28,6 @@ ifeq ($(CONFIG_ARCH_RV64I),y)

KBUILD_CFLAGS   += $(call cc-ifversion, -ge, 0500, 
-DCONFIG_ARCH_SUPPORTS_INT128)
 
-   KBUILD_MARCH = rv64im
KBUILD_LDFLAGS += -melf64lriscv
 else
BITS := 32
@@ -36,22 +35,20 @@ else
 
KBUILD_CFLAGS += -mabi=ilp32
KBUILD_AFLAGS += -mabi=ilp32
-   KBUILD_MARCH = rv32im
KBUILD_LDFLAGS += -melf32lriscv
 endif
 
 KBUILD_CFLAGS += -Wall
 
-ifeq ($(CONFIG_RISCV_ISA_A),y)
-   KBUILD_ARCH_A = a
-endif
-ifeq ($(CONFIG_RISCV_ISA_C),y)
-   KBUILD_ARCH_C = c
-endif
-
-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+# ISA string setting
+riscv-march-$(CONFIG_ARCH_RV32I)   := rv32im
+riscv-march-$(CONFIG_ARCH_RV64I)   := rv64im
+riscv-march-$(CONFIG_RISCV_ISA_A)  := $(riscv-march-y)a
+riscv-march-y  := $(riscv-march-y)fd
+riscv-march-$(CONFIG_RISCV_ISA_C)  := $(riscv-march-y)c
+KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
+KBUILD_AFLAGS += -march=$(riscv-march-y)
 
-KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
 KBUILD_CFLAGS += -mno-save-restore
 KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
 
-- 
2.7.4



[PATCH v8 1/5] Extract FPU context operations from entry.S

2018-10-08 Thread Alan Kao
We move __fstate_save and __fstate_restore to a new source
file, fpu.S.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/entry.S  |  87 -
 arch/riscv/kernel/fpu.S| 106 +
 3 files changed, 107 insertions(+), 87 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index e1274fc..bd433efd 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,6 +13,7 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
+obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index fa2c08e..59c02e2 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -357,93 +357,6 @@ ENTRY(__switch_to)
ret
 ENDPROC(__switch_to)
 
-ENTRY(__fstate_save)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   csrs sstatus, t1
-   frcsr t0
-   fsd f0,  TASK_THREAD_F0_F0(a0)
-   fsd f1,  TASK_THREAD_F1_F0(a0)
-   fsd f2,  TASK_THREAD_F2_F0(a0)
-   fsd f3,  TASK_THREAD_F3_F0(a0)
-   fsd f4,  TASK_THREAD_F4_F0(a0)
-   fsd f5,  TASK_THREAD_F5_F0(a0)
-   fsd f6,  TASK_THREAD_F6_F0(a0)
-   fsd f7,  TASK_THREAD_F7_F0(a0)
-   fsd f8,  TASK_THREAD_F8_F0(a0)
-   fsd f9,  TASK_THREAD_F9_F0(a0)
-   fsd f10, TASK_THREAD_F10_F0(a0)
-   fsd f11, TASK_THREAD_F11_F0(a0)
-   fsd f12, TASK_THREAD_F12_F0(a0)
-   fsd f13, TASK_THREAD_F13_F0(a0)
-   fsd f14, TASK_THREAD_F14_F0(a0)
-   fsd f15, TASK_THREAD_F15_F0(a0)
-   fsd f16, TASK_THREAD_F16_F0(a0)
-   fsd f17, TASK_THREAD_F17_F0(a0)
-   fsd f18, TASK_THREAD_F18_F0(a0)
-   fsd f19, TASK_THREAD_F19_F0(a0)
-   fsd f20, TASK_THREAD_F20_F0(a0)
-   fsd f21, TASK_THREAD_F21_F0(a0)
-   fsd f22, TASK_THREAD_F22_F0(a0)
-   fsd f23, TASK_THREAD_F23_F0(a0)
-   fsd f24, TASK_THREAD_F24_F0(a0)
-   fsd f25, TASK_THREAD_F25_F0(a0)
-   fsd f26, TASK_THREAD_F26_F0(a0)
-   fsd f27, TASK_THREAD_F27_F0(a0)
-   fsd f28, TASK_THREAD_F28_F0(a0)
-   fsd f29, TASK_THREAD_F29_F0(a0)
-   fsd f30, TASK_THREAD_F30_F0(a0)
-   fsd f31, TASK_THREAD_F31_F0(a0)
-   sw t0, TASK_THREAD_FCSR_F0(a0)
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_save)
-
-ENTRY(__fstate_restore)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   lw t0, TASK_THREAD_FCSR_F0(a0)
-   csrs sstatus, t1
-   fld f0,  TASK_THREAD_F0_F0(a0)
-   fld f1,  TASK_THREAD_F1_F0(a0)
-   fld f2,  TASK_THREAD_F2_F0(a0)
-   fld f3,  TASK_THREAD_F3_F0(a0)
-   fld f4,  TASK_THREAD_F4_F0(a0)
-   fld f5,  TASK_THREAD_F5_F0(a0)
-   fld f6,  TASK_THREAD_F6_F0(a0)
-   fld f7,  TASK_THREAD_F7_F0(a0)
-   fld f8,  TASK_THREAD_F8_F0(a0)
-   fld f9,  TASK_THREAD_F9_F0(a0)
-   fld f10, TASK_THREAD_F10_F0(a0)
-   fld f11, TASK_THREAD_F11_F0(a0)
-   fld f12, TASK_THREAD_F12_F0(a0)
-   fld f13, TASK_THREAD_F13_F0(a0)
-   fld f14, TASK_THREAD_F14_F0(a0)
-   fld f15, TASK_THREAD_F15_F0(a0)
-   fld f16, TASK_THREAD_F16_F0(a0)
-   fld f17, TASK_THREAD_F17_F0(a0)
-   fld f18, TASK_THREAD_F18_F0(a0)
-   fld f19, TASK_THREAD_F19_F0(a0)
-   fld f20, TASK_THREAD_F20_F0(a0)
-   fld f21, TASK_THREAD_F21_F0(a0)
-   fld f22, TASK_THREAD_F22_F0(a0)
-   fld f23, TASK_THREAD_F23_F0(a0)
-   fld f24, TASK_THREAD_F24_F0(a0)
-   fld f25, TASK_THREAD_F25_F0(a0)
-   fld f26, TASK_THREAD_F26_F0(a0)
-   fld f27, TASK_THREAD_F27_F0(a0)
-   fld f28, TASK_THREAD_F28_F0(a0)
-   fld f29, TASK_THREAD_F29_F0(a0)
-   fld f30, TASK_THREAD_F30_F0(a0)
-   fld f31, TASK_THREAD_F31_F0(a0)
-   fscsr t0
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_restore)
-
-
.section ".rodata"
/* Exception vector table */
 ENTRY(excp_vect_table)
diff --git a/arch/riscv/kernel/fpu.S b/arch/riscv/kernel/fpu.S
new file mode 100644
index 000..1defb06
--- /dev/null
+++ b/arch/riscv/kernel/fpu.S
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2012 Regents of the University of California
+ * Copyright (C) 2017 SiFive
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include 
+
+#include 

[PATCH v8 3/5] Cleanup ISA string setting

2018-10-08 Thread Alan Kao
This patch cleanup the MARCH string passing to both compiler and
assembler.  Note that the CFLAGS should not contain "fd" before we
have mechnisms like kernel_fpu_begin/end in other architectures.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/Makefile | 19 ---
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 61ec424..01393e1 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -28,7 +28,6 @@ ifeq ($(CONFIG_ARCH_RV64I),y)

KBUILD_CFLAGS   += $(call cc-ifversion, -ge, 0500, 
-DCONFIG_ARCH_SUPPORTS_INT128)
 
-   KBUILD_MARCH = rv64im
KBUILD_LDFLAGS += -melf64lriscv
 else
BITS := 32
@@ -36,22 +35,20 @@ else
 
KBUILD_CFLAGS += -mabi=ilp32
KBUILD_AFLAGS += -mabi=ilp32
-   KBUILD_MARCH = rv32im
KBUILD_LDFLAGS += -melf32lriscv
 endif
 
 KBUILD_CFLAGS += -Wall
 
-ifeq ($(CONFIG_RISCV_ISA_A),y)
-   KBUILD_ARCH_A = a
-endif
-ifeq ($(CONFIG_RISCV_ISA_C),y)
-   KBUILD_ARCH_C = c
-endif
-
-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+# ISA string setting
+riscv-march-$(CONFIG_ARCH_RV32I)   := rv32im
+riscv-march-$(CONFIG_ARCH_RV64I)   := rv64im
+riscv-march-$(CONFIG_RISCV_ISA_A)  := $(riscv-march-y)a
+riscv-march-y  := $(riscv-march-y)fd
+riscv-march-$(CONFIG_RISCV_ISA_C)  := $(riscv-march-y)c
+KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
+KBUILD_AFLAGS += -march=$(riscv-march-y)
 
-KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
 KBUILD_CFLAGS += -mno-save-restore
 KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
 
-- 
2.7.4



[PATCH v8 5/5] Auto-detect whether a FPU exists

2018-10-08 Thread Alan Kao
We expect that a kernel with CONFIG_FPU=y can still support no-FPU
machines. To do so, the kernel should first examine the existence of a
FPU, then do nothing if a FPU does exist; otherwise, it should
disable/bypass all FPU-related functions.

In this patch, a new global variable, has_fpu, is created and determined
when parsing the hardware capability from device tree during booting.
This variable is used in those FPU-related functions.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/include/asm/switch_to.h | 8 
 arch/riscv/kernel/cpufeature.c | 8 
 arch/riscv/kernel/process.c| 4 +++-
 arch/riscv/kernel/signal.c | 6 --
 4 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index 093050b..7335590 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -56,13 +56,12 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
-
+extern bool has_fpu;
 #else
+#define has_fpu false
 #define fstate_save(task, regs) do { } while (0)
 #define fstate_restore(task, regs) do { } while (0)
 #define __switch_to_aux(__prev, __next) do { } while (0)
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
 #endif
 
 extern struct task_struct *__switch_to(struct task_struct *,
@@ -72,7 +71,8 @@ extern struct task_struct *__switch_to(struct task_struct *,
 do {   \
struct task_struct *__prev = (prev);\
struct task_struct *__next = (next);\
-   __switch_to_aux(__prev, __next);\
+   if (has_fpu)\
+   __switch_to_aux(__prev, __next);\
((last) = __switch_to(__prev, __next)); \
 } while (0)
 
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 17011a8..46942e6 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -22,6 +22,9 @@
 #include 
 
 unsigned long elf_hwcap __read_mostly;
+#ifdef CONFIG_FPU
+bool has_fpu __read_mostly;
+#endif
 
 void riscv_fill_hwcap(void)
 {
@@ -58,4 +61,9 @@ void riscv_fill_hwcap(void)
elf_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
 
pr_info("elf_hwcap is 0x%lx", elf_hwcap);
+
+#ifdef CONFIG_FPU
+   if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
+   has_fpu = true;
+#endif
 }
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index 07d5156..bef1999 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -76,7 +76,9 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = DEFAULT_SSTATUS;
+   regs->sstatus = SR_SPIE;
+   if (has_fpu)
+   regs->sstatus |= SR_FS_INITIAL;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 2450b82..f9b5e7e 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -98,7 +98,8 @@ static long restore_sigcontext(struct pt_regs *regs,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
/* Restore the floating-point state. */
-   err |= restore_fp_state(regs, >sc_fpregs);
+   if (has_fpu)
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -150,7 +151,8 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_fp_state(regs, >sc_fpregs);
+   if (has_fpu)
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.7.4



[PATCH v8 5/5] Auto-detect whether a FPU exists

2018-10-08 Thread Alan Kao
We expect that a kernel with CONFIG_FPU=y can still support no-FPU
machines. To do so, the kernel should first examine the existence of a
FPU, then do nothing if a FPU does exist; otherwise, it should
disable/bypass all FPU-related functions.

In this patch, a new global variable, has_fpu, is created and determined
when parsing the hardware capability from device tree during booting.
This variable is used in those FPU-related functions.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/include/asm/switch_to.h | 8 
 arch/riscv/kernel/cpufeature.c | 8 
 arch/riscv/kernel/process.c| 4 +++-
 arch/riscv/kernel/signal.c | 6 --
 4 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index 093050b..7335590 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -56,13 +56,12 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
-
+extern bool has_fpu;
 #else
+#define has_fpu false
 #define fstate_save(task, regs) do { } while (0)
 #define fstate_restore(task, regs) do { } while (0)
 #define __switch_to_aux(__prev, __next) do { } while (0)
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
 #endif
 
 extern struct task_struct *__switch_to(struct task_struct *,
@@ -72,7 +71,8 @@ extern struct task_struct *__switch_to(struct task_struct *,
 do {   \
struct task_struct *__prev = (prev);\
struct task_struct *__next = (next);\
-   __switch_to_aux(__prev, __next);\
+   if (has_fpu)\
+   __switch_to_aux(__prev, __next);\
((last) = __switch_to(__prev, __next)); \
 } while (0)
 
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 17011a8..46942e6 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -22,6 +22,9 @@
 #include 
 
 unsigned long elf_hwcap __read_mostly;
+#ifdef CONFIG_FPU
+bool has_fpu __read_mostly;
+#endif
 
 void riscv_fill_hwcap(void)
 {
@@ -58,4 +61,9 @@ void riscv_fill_hwcap(void)
elf_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
 
pr_info("elf_hwcap is 0x%lx", elf_hwcap);
+
+#ifdef CONFIG_FPU
+   if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
+   has_fpu = true;
+#endif
 }
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index 07d5156..bef1999 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -76,7 +76,9 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = DEFAULT_SSTATUS;
+   regs->sstatus = SR_SPIE;
+   if (has_fpu)
+   regs->sstatus |= SR_FS_INITIAL;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 2450b82..f9b5e7e 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -98,7 +98,8 @@ static long restore_sigcontext(struct pt_regs *regs,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
/* Restore the floating-point state. */
-   err |= restore_fp_state(regs, >sc_fpregs);
+   if (has_fpu)
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -150,7 +151,8 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_fp_state(regs, >sc_fpregs);
+   if (has_fpu)
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.7.4



[PATCH v8 2/5] Refactor FPU code in signal setup/return procedures

2018-10-08 Thread Alan Kao
FPU-related logic is separated from normal signal handling path in
this patch.  Kernel can easily be configured to exclude those procedures
for no-FPU systems.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/kernel/signal.c | 68 --
 1 file changed, 41 insertions(+), 27 deletions(-)

diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 718d0c9..6a18b98 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,45 +37,63 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
-static long restore_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long restore_fp_state(struct pt_regs *regs,
+union __riscv_fp_state *sc_fpregs)
 {
long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
err = __copy_from_user(>thread.fstate, state, sizeof(*state));
-   if (likely(!err))
-   fstate_restore(current, regs);
+   if (unlikely(err))
+   return err;
+
+   fstate_restore(current, regs);
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   u32 value;
+
+   err = __get_user(value, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   if (value != 0)
+   return -EINVAL;
+   }
+
return err;
 }
 
-static long save_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long save_fp_state(struct pt_regs *regs,
+ union __riscv_fp_state *sc_fpregs)
 {
+   long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
fstate_save(current, regs);
-   return __copy_to_user(state, >thread.fstate, sizeof(*state));
+   err = __copy_to_user(state, >thread.fstate, sizeof(*state));
+   if (unlikely(err))
+   return err;
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   err = __put_user(0, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   }
+
+   return err;
 }
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
 {
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
-   if (unlikely(err))
-   return err;
/* Restore the floating-point state. */
-   err = restore_d_state(regs, >sc_fpregs.d);
-   if (unlikely(err))
-   return err;
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) {
-   u32 value;
-   err = __get_user(value, >sc_fpregs.q.reserved[i]);
-   if (unlikely(err))
-   break;
-   if (value != 0)
-   return -EINVAL;
-   }
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -124,14 +142,10 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
 {
struct sigcontext __user *sc = >uc.uc_mcontext;
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_d_state(regs, >sc_fpregs.d);
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++)
-   err |= __put_user(0, >sc_fpregs.q.reserved[i]);
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.7.4



[PATCH v8 2/5] Refactor FPU code in signal setup/return procedures

2018-10-08 Thread Alan Kao
FPU-related logic is separated from normal signal handling path in
this patch.  Kernel can easily be configured to exclude those procedures
for no-FPU systems.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/kernel/signal.c | 68 --
 1 file changed, 41 insertions(+), 27 deletions(-)

diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 718d0c9..6a18b98 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,45 +37,63 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
-static long restore_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long restore_fp_state(struct pt_regs *regs,
+union __riscv_fp_state *sc_fpregs)
 {
long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
err = __copy_from_user(>thread.fstate, state, sizeof(*state));
-   if (likely(!err))
-   fstate_restore(current, regs);
+   if (unlikely(err))
+   return err;
+
+   fstate_restore(current, regs);
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   u32 value;
+
+   err = __get_user(value, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   if (value != 0)
+   return -EINVAL;
+   }
+
return err;
 }
 
-static long save_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long save_fp_state(struct pt_regs *regs,
+ union __riscv_fp_state *sc_fpregs)
 {
+   long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
fstate_save(current, regs);
-   return __copy_to_user(state, >thread.fstate, sizeof(*state));
+   err = __copy_to_user(state, >thread.fstate, sizeof(*state));
+   if (unlikely(err))
+   return err;
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   err = __put_user(0, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   }
+
+   return err;
 }
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
 {
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
-   if (unlikely(err))
-   return err;
/* Restore the floating-point state. */
-   err = restore_d_state(regs, >sc_fpregs.d);
-   if (unlikely(err))
-   return err;
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) {
-   u32 value;
-   err = __get_user(value, >sc_fpregs.q.reserved[i]);
-   if (unlikely(err))
-   break;
-   if (value != 0)
-   return -EINVAL;
-   }
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -124,14 +142,10 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
 {
struct sigcontext __user *sc = >uc.uc_mcontext;
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_d_state(regs, >sc_fpregs.d);
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++)
-   err |= __put_user(0, >sc_fpregs.q.reserved[i]);
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.7.4



[PATCH v8 0/5] riscv: Add support to no-FPU systems

2018-10-08 Thread Alan Kao
This patchset adds an option, CONFIG_FPU, to enable/disable floating-
point procedures.

Kernel's new behavior will be as follows:

* with CONFIG_FPU=y
  All FPU codes are reserved.  If no FPU is found during booting, a
  global flag will be set, and those functions will be bypassed with
  condition check to that flag.

* with CONFIG_FPU=n
  No floating-point instructions in kernel and all related settings
  are excluded.

Changes in v8:
 - Fix a build fail introduced in v7.

Changes in v7:
 - Remove "fd" attribute from KBUILD_CFLAGS.

Changes in v6 (PATCH 0005 only):
 - Make the flag checking neater.

Changes in v5:
 - Invert the polarity of checking flag from no_fpu to has_fpu.

Changes in v4:
 - Append a new patch to detect existence of FPU and followups.
 - Add SPDX header to newly created fpu.S.
 - Fix a build error, sorry for that.
 - Fix wording, style, etc.

Changes in v3:
 - Refactor the whole patch into independent ones.

Changes in v2:
 - Various code cleanups and style fixes.

Alan Kao (5):
  Extract FPU context operations from entry.S
  Refactor FPU code in signal setup/return procedures
  Cleanup ISA string setting
  Allow to disable FPU support
  Auto-detect whether a FPU exists

 arch/riscv/Kconfig |   9 
 arch/riscv/Makefile|  19 +++
 arch/riscv/include/asm/switch_to.h |  12 -
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/cpufeature.c |   8 +++
 arch/riscv/kernel/entry.S  |  87 --
 arch/riscv/kernel/fpu.S| 106 +
 arch/riscv/kernel/process.c|   6 ++-
 arch/riscv/kernel/signal.c |  75 --
 9 files changed, 196 insertions(+), 127 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

-- 
2.7.4



[PATCH v8 4/5] Allow to disable FPU support

2018-10-08 Thread Alan Kao
FPU codes have been separated from common part in previous patches.
This patch add the CONFIG_FPU option and some stubs, so that a no-FPU
configuration is allowed.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/Kconfig |  9 +
 arch/riscv/Makefile|  2 +-
 arch/riscv/include/asm/switch_to.h | 10 ++
 arch/riscv/kernel/Makefile |  2 +-
 arch/riscv/kernel/process.c|  4 +++-
 arch/riscv/kernel/signal.c |  5 +
 6 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index a344980..a63f9db 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -208,6 +208,15 @@ config RISCV_BASE_PMU
 
 endmenu
 
+config FPU
+   bool "FPU support"
+   default y
+   help
+ Say N here if you want to disable all floating-point related procedure
+ in the kernel.
+
+ If you don't know what to do here, say Y.
+
 endmenu
 
 menu "Kernel type"
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 01393e1..901770f 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -44,7 +44,7 @@ KBUILD_CFLAGS += -Wall
 riscv-march-$(CONFIG_ARCH_RV32I)   := rv32im
 riscv-march-$(CONFIG_ARCH_RV64I)   := rv64im
 riscv-march-$(CONFIG_RISCV_ISA_A)  := $(riscv-march-y)a
-riscv-march-y  := $(riscv-march-y)fd
+riscv-march-$(CONFIG_FPU)  := $(riscv-march-y)fd
 riscv-march-$(CONFIG_RISCV_ISA_C)  := $(riscv-march-y)c
 KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
 KBUILD_AFLAGS += -march=$(riscv-march-y)
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index dd6b05b..093050b 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -18,6 +18,7 @@
 #include 
 #include 
 
+#ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
 extern void __fstate_restore(struct task_struct *restore_from);
 
@@ -55,6 +56,15 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
+
+#else
+#define fstate_save(task, regs) do { } while (0)
+#define fstate_restore(task, regs) do { } while (0)
+#define __switch_to_aux(__prev, __next) do { } while (0)
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
+#endif
+
 extern struct task_struct *__switch_to(struct task_struct *,
   struct task_struct *);
 
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index bd433efd..f13f7f2 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,7 +13,6 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
-obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
@@ -32,6 +31,7 @@ obj-y += vdso/
 
 CFLAGS_setup.o := -mcmodel=medany
 
+obj-$(CONFIG_FPU)  += fpu.o
 obj-$(CONFIG_SMP)  += smpboot.o
 obj-$(CONFIG_SMP)  += smp.o
 obj-$(CONFIG_MODULES)  += module.o
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index d7c6ca7..07d5156 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -76,7 +76,7 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
+   regs->sstatus = DEFAULT_SSTATUS;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
@@ -84,12 +84,14 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
 
 void flush_thread(void)
 {
+#ifdef CONFIG_FPU
/*
 * Reset FPU context
 *  frm: round to nearest, ties to even (IEEE default)
 *  fflags: accrued exceptions cleared
 */
memset(>thread.fstate, 0, sizeof(current->thread.fstate));
+#endif
 }
 
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 6a18b98..2450b82 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,6 +37,7 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
+#ifdef CONFIG_FPU
 static long restore_fp_state(struct pt_regs *regs,
 union __riscv_fp_state *sc_fpregs)
 {
@@ -85,6 +86,10 @@ static long save_fp_state(struct pt_regs *regs,
 
return err;
 }
+#else
+#define save_fp_state(task, regs) (0)
+#define restore_fp_state(task, regs) (0)
+#endif
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
-- 
2.7.4



[PATCH v8 0/5] riscv: Add support to no-FPU systems

2018-10-08 Thread Alan Kao
This patchset adds an option, CONFIG_FPU, to enable/disable floating-
point procedures.

Kernel's new behavior will be as follows:

* with CONFIG_FPU=y
  All FPU codes are reserved.  If no FPU is found during booting, a
  global flag will be set, and those functions will be bypassed with
  condition check to that flag.

* with CONFIG_FPU=n
  No floating-point instructions in kernel and all related settings
  are excluded.

Changes in v8:
 - Fix a build fail introduced in v7.

Changes in v7:
 - Remove "fd" attribute from KBUILD_CFLAGS.

Changes in v6 (PATCH 0005 only):
 - Make the flag checking neater.

Changes in v5:
 - Invert the polarity of checking flag from no_fpu to has_fpu.

Changes in v4:
 - Append a new patch to detect existence of FPU and followups.
 - Add SPDX header to newly created fpu.S.
 - Fix a build error, sorry for that.
 - Fix wording, style, etc.

Changes in v3:
 - Refactor the whole patch into independent ones.

Changes in v2:
 - Various code cleanups and style fixes.

Alan Kao (5):
  Extract FPU context operations from entry.S
  Refactor FPU code in signal setup/return procedures
  Cleanup ISA string setting
  Allow to disable FPU support
  Auto-detect whether a FPU exists

 arch/riscv/Kconfig |   9 
 arch/riscv/Makefile|  19 +++
 arch/riscv/include/asm/switch_to.h |  12 -
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/cpufeature.c |   8 +++
 arch/riscv/kernel/entry.S  |  87 --
 arch/riscv/kernel/fpu.S| 106 +
 arch/riscv/kernel/process.c|   6 ++-
 arch/riscv/kernel/signal.c |  75 --
 9 files changed, 196 insertions(+), 127 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

-- 
2.7.4



[PATCH v8 4/5] Allow to disable FPU support

2018-10-08 Thread Alan Kao
FPU codes have been separated from common part in previous patches.
This patch add the CONFIG_FPU option and some stubs, so that a no-FPU
configuration is allowed.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/Kconfig |  9 +
 arch/riscv/Makefile|  2 +-
 arch/riscv/include/asm/switch_to.h | 10 ++
 arch/riscv/kernel/Makefile |  2 +-
 arch/riscv/kernel/process.c|  4 +++-
 arch/riscv/kernel/signal.c |  5 +
 6 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index a344980..a63f9db 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -208,6 +208,15 @@ config RISCV_BASE_PMU
 
 endmenu
 
+config FPU
+   bool "FPU support"
+   default y
+   help
+ Say N here if you want to disable all floating-point related procedure
+ in the kernel.
+
+ If you don't know what to do here, say Y.
+
 endmenu
 
 menu "Kernel type"
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 01393e1..901770f 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -44,7 +44,7 @@ KBUILD_CFLAGS += -Wall
 riscv-march-$(CONFIG_ARCH_RV32I)   := rv32im
 riscv-march-$(CONFIG_ARCH_RV64I)   := rv64im
 riscv-march-$(CONFIG_RISCV_ISA_A)  := $(riscv-march-y)a
-riscv-march-y  := $(riscv-march-y)fd
+riscv-march-$(CONFIG_FPU)  := $(riscv-march-y)fd
 riscv-march-$(CONFIG_RISCV_ISA_C)  := $(riscv-march-y)c
 KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
 KBUILD_AFLAGS += -march=$(riscv-march-y)
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index dd6b05b..093050b 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -18,6 +18,7 @@
 #include 
 #include 
 
+#ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
 extern void __fstate_restore(struct task_struct *restore_from);
 
@@ -55,6 +56,15 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
+
+#else
+#define fstate_save(task, regs) do { } while (0)
+#define fstate_restore(task, regs) do { } while (0)
+#define __switch_to_aux(__prev, __next) do { } while (0)
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
+#endif
+
 extern struct task_struct *__switch_to(struct task_struct *,
   struct task_struct *);
 
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index bd433efd..f13f7f2 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,7 +13,6 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
-obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
@@ -32,6 +31,7 @@ obj-y += vdso/
 
 CFLAGS_setup.o := -mcmodel=medany
 
+obj-$(CONFIG_FPU)  += fpu.o
 obj-$(CONFIG_SMP)  += smpboot.o
 obj-$(CONFIG_SMP)  += smp.o
 obj-$(CONFIG_MODULES)  += module.o
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index d7c6ca7..07d5156 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -76,7 +76,7 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
+   regs->sstatus = DEFAULT_SSTATUS;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
@@ -84,12 +84,14 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
 
 void flush_thread(void)
 {
+#ifdef CONFIG_FPU
/*
 * Reset FPU context
 *  frm: round to nearest, ties to even (IEEE default)
 *  fflags: accrued exceptions cleared
 */
memset(>thread.fstate, 0, sizeof(current->thread.fstate));
+#endif
 }
 
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 6a18b98..2450b82 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,6 +37,7 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
+#ifdef CONFIG_FPU
 static long restore_fp_state(struct pt_regs *regs,
 union __riscv_fp_state *sc_fpregs)
 {
@@ -85,6 +86,10 @@ static long save_fp_state(struct pt_regs *regs,
 
return err;
 }
+#else
+#define save_fp_state(task, regs) (0)
+#define restore_fp_state(task, regs) (0)
+#endif
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
-- 
2.7.4



Re: [PATCH v7 0/5] riscv: Add support to no-FPU systems

2018-10-04 Thread Alan Kao
On Thu, Sep 06, 2018 at 02:45:04AM -0700, Palmer Dabbelt wrote:
> On Sun, 26 Aug 2018 18:07:50 PDT (-0700), alan...@andestech.com wrote:
> >This patchset adds an option, CONFIG_FPU, to enable/disable floating-
> >point procedures.
> >
> >Kernel's new behavior will be as follows:
> >
> >* with CONFIG_FPU=y
> >  All FPU codes are reserved.  If no FPU is found during booting, a
> >  global flag will be set, and those functions will be bypassed with
> >  condition check to that flag.
> >
> >* with CONFIG_FPU=n
> >  No floating-point instructions in kernel and all related settings
> >  are excluded.
> >
> >Changes in v7:
> > - Remove "fd" attribute from KBUILD_CFLAGS.
> >
> >Changes in v6 (PATCH 0005 only):
> > - Make the flag checking neater.
> >
> >Changes in v5:
> > - Invert the polarity of checking flag from no_fpu to has_fpu.
> >
> >Changes in v4:
> > - Append a new patch to detect existence of FPU and followups.
> > - Add SPDX header to newly created fpu.S.
> > - Fix a build error, sorry for that.
> > - Fix wording, style, etc.
> >
> >Changes in v3:
> > - Refactor the whole patch into independent ones.
> >
> >Changes in v2:
> > - Various code cleanups and style fixes.
> >
> >
> >Alan Kao (5):
> >  Extract FPU context operations from entry.S
> >  Refactor FPU code in signal setup/return procedures
> >  Cleanup ISA string setting
> >  Allow to disable FPU support
> >  Auto-detect whether a FPU exists
> >
> > arch/riscv/Kconfig |   9 +++
> > arch/riscv/Makefile|  19 +++---
> > arch/riscv/include/asm/switch_to.h |  12 +++-
> > arch/riscv/kernel/Makefile |   1 +
> > arch/riscv/kernel/cpufeature.c |   8 +++
> > arch/riscv/kernel/entry.S  |  87 ---
> > arch/riscv/kernel/fpu.S| 106 +
> > arch/riscv/kernel/process.c|   6 +-
> > arch/riscv/kernel/signal.c |  75 
> > 9 files changed, 196 insertions(+), 127 deletions(-)
> > create mode 100644 arch/riscv/kernel/fpu.S
> 
> Thanks!  I'll add this to our for-next branch.

Any updates?


Re: [PATCH v7 0/5] riscv: Add support to no-FPU systems

2018-10-04 Thread Alan Kao
On Thu, Sep 06, 2018 at 02:45:04AM -0700, Palmer Dabbelt wrote:
> On Sun, 26 Aug 2018 18:07:50 PDT (-0700), alan...@andestech.com wrote:
> >This patchset adds an option, CONFIG_FPU, to enable/disable floating-
> >point procedures.
> >
> >Kernel's new behavior will be as follows:
> >
> >* with CONFIG_FPU=y
> >  All FPU codes are reserved.  If no FPU is found during booting, a
> >  global flag will be set, and those functions will be bypassed with
> >  condition check to that flag.
> >
> >* with CONFIG_FPU=n
> >  No floating-point instructions in kernel and all related settings
> >  are excluded.
> >
> >Changes in v7:
> > - Remove "fd" attribute from KBUILD_CFLAGS.
> >
> >Changes in v6 (PATCH 0005 only):
> > - Make the flag checking neater.
> >
> >Changes in v5:
> > - Invert the polarity of checking flag from no_fpu to has_fpu.
> >
> >Changes in v4:
> > - Append a new patch to detect existence of FPU and followups.
> > - Add SPDX header to newly created fpu.S.
> > - Fix a build error, sorry for that.
> > - Fix wording, style, etc.
> >
> >Changes in v3:
> > - Refactor the whole patch into independent ones.
> >
> >Changes in v2:
> > - Various code cleanups and style fixes.
> >
> >
> >Alan Kao (5):
> >  Extract FPU context operations from entry.S
> >  Refactor FPU code in signal setup/return procedures
> >  Cleanup ISA string setting
> >  Allow to disable FPU support
> >  Auto-detect whether a FPU exists
> >
> > arch/riscv/Kconfig |   9 +++
> > arch/riscv/Makefile|  19 +++---
> > arch/riscv/include/asm/switch_to.h |  12 +++-
> > arch/riscv/kernel/Makefile |   1 +
> > arch/riscv/kernel/cpufeature.c |   8 +++
> > arch/riscv/kernel/entry.S  |  87 ---
> > arch/riscv/kernel/fpu.S| 106 +
> > arch/riscv/kernel/process.c|   6 +-
> > arch/riscv/kernel/signal.c |  75 
> > 9 files changed, 196 insertions(+), 127 deletions(-)
> > create mode 100644 arch/riscv/kernel/fpu.S
> 
> Thanks!  I'll add this to our for-next branch.

Any updates?


Re: [PATCH] RISC-V: Mask out the F extension on systems without D

2018-08-28 Thread Alan Kao
Hi Palmer,

On Mon, Aug 27, 2018 at 03:03:52PM -0700, Palmer Dabbelt wrote:
> The RISC-V Linux port doesn't support systems that have the F extension
> but don't have the D extension -- we actually don't support systems
> without D either, but Alan's patch set is rectifying that soon.  For now
> I think we can leave this in a semi-broken state and just wait for
> Alan's patch set to get merged for proper non-FPU support -- the patch
> set is starting to look good, so doing something in-between doesn't seem
> like it's worth the work.
> 
> I don't think it's worth fretting about support for systems with F but
> not D for now: our glibc ABIs are IMAC and IMAFDC so they probably won't
> end up being popular.  We can always extend this in the future.
> 
> CC: Alan Kao 
> Signed-off-by: Palmer Dabbelt 
> ---
>  arch/riscv/kernel/cpufeature.c | 7 +++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
> index 17011a870044..652d102ffa06 100644
> --- a/arch/riscv/kernel/cpufeature.c
> +++ b/arch/riscv/kernel/cpufeature.c
> @@ -57,5 +57,12 @@ void riscv_fill_hwcap(void)
>   for (i = 0; i < strlen(isa); ++i)
>   elf_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
>  
> + /* We don't support systems with F but without D, so mask those out
> +  * here. */
> + if ((elf_hwcap & COMPAT_HWCAP_ISA_F) && !(elf_hwcap & 
> COMPAT_HWCAP_ISA_D)) {
> + pr_info("This kernel does not support systems with F but not 
> D");
> + elf_hwcap &= ~COMPAT_HWCAP_ISA_F;
> + }
> +

The commit message does address the problem and this patch does provide checks
and helpful information to users, but I wonder if we really need this patch, for
two reasons:

* Just as you mentioned, current glibc ABI does not support such a thing as
  IMAFC, so probably no one has had trouble with this.  To be honest, I suppose
  that anybody (RISC-V enthusiasts or vendors) who really need F-only support
  in kernel should get themself involved in the development by sending patches
  to improve.

* There are corner cases to let a F-only machine to pass the check in this
  patch.  For instance, a vendor decides to name her extension ISA as doom,
  and supports single-precision FP only, so her ISA string would be

IMAFCXdoom.

  The variable elf_hwcap is calculated at the loop in line 57,58, the 'd'
  from Xdoom would bypass the check, while the underlying machine does not
  support double-precision FP.

>   pr_info("elf_hwcap is 0x%lx", elf_hwcap);
>  }
> -- 
> 2.16.4
>

I don't know if the reasons make sense to you, but anyway that's all I
would like to say about this patch.

Alan


Re: [PATCH] RISC-V: Mask out the F extension on systems without D

2018-08-28 Thread Alan Kao
Hi Palmer,

On Mon, Aug 27, 2018 at 03:03:52PM -0700, Palmer Dabbelt wrote:
> The RISC-V Linux port doesn't support systems that have the F extension
> but don't have the D extension -- we actually don't support systems
> without D either, but Alan's patch set is rectifying that soon.  For now
> I think we can leave this in a semi-broken state and just wait for
> Alan's patch set to get merged for proper non-FPU support -- the patch
> set is starting to look good, so doing something in-between doesn't seem
> like it's worth the work.
> 
> I don't think it's worth fretting about support for systems with F but
> not D for now: our glibc ABIs are IMAC and IMAFDC so they probably won't
> end up being popular.  We can always extend this in the future.
> 
> CC: Alan Kao 
> Signed-off-by: Palmer Dabbelt 
> ---
>  arch/riscv/kernel/cpufeature.c | 7 +++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
> index 17011a870044..652d102ffa06 100644
> --- a/arch/riscv/kernel/cpufeature.c
> +++ b/arch/riscv/kernel/cpufeature.c
> @@ -57,5 +57,12 @@ void riscv_fill_hwcap(void)
>   for (i = 0; i < strlen(isa); ++i)
>   elf_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
>  
> + /* We don't support systems with F but without D, so mask those out
> +  * here. */
> + if ((elf_hwcap & COMPAT_HWCAP_ISA_F) && !(elf_hwcap & 
> COMPAT_HWCAP_ISA_D)) {
> + pr_info("This kernel does not support systems with F but not 
> D");
> + elf_hwcap &= ~COMPAT_HWCAP_ISA_F;
> + }
> +

The commit message does address the problem and this patch does provide checks
and helpful information to users, but I wonder if we really need this patch, for
two reasons:

* Just as you mentioned, current glibc ABI does not support such a thing as
  IMAFC, so probably no one has had trouble with this.  To be honest, I suppose
  that anybody (RISC-V enthusiasts or vendors) who really need F-only support
  in kernel should get themself involved in the development by sending patches
  to improve.

* There are corner cases to let a F-only machine to pass the check in this
  patch.  For instance, a vendor decides to name her extension ISA as doom,
  and supports single-precision FP only, so her ISA string would be

IMAFCXdoom.

  The variable elf_hwcap is calculated at the loop in line 57,58, the 'd'
  from Xdoom would bypass the check, while the underlying machine does not
  support double-precision FP.

>   pr_info("elf_hwcap is 0x%lx", elf_hwcap);
>  }
> -- 
> 2.16.4
>

I don't know if the reasons make sense to you, but anyway that's all I
would like to say about this patch.

Alan


[PATCH 5/5] Auto-detect whether a FPU exists

2018-08-26 Thread Alan Kao
We expect that a kernel with CONFIG_FPU=y can still support no-FPU
machines. To do so, the kernel should first examine the existence of a
FPU, then do nothing if a FPU does exist; otherwise, it should
disable/bypass all FPU-related functions.

In this patch, a new global variable, has_fpu, is created and determined
when parsing the hardware capability from device tree during booting.
This variable is used in those FPU-related functions.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/include/asm/switch_to.h | 8 
 arch/riscv/kernel/cpufeature.c | 8 
 arch/riscv/kernel/process.c| 4 +++-
 arch/riscv/kernel/signal.c | 6 --
 4 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index 093050b03543..733559083f24 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -56,13 +56,12 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
-
+extern bool has_fpu;
 #else
+#define has_fpu false
 #define fstate_save(task, regs) do { } while (0)
 #define fstate_restore(task, regs) do { } while (0)
 #define __switch_to_aux(__prev, __next) do { } while (0)
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
 #endif
 
 extern struct task_struct *__switch_to(struct task_struct *,
@@ -72,7 +71,8 @@ extern struct task_struct *__switch_to(struct task_struct *,
 do {   \
struct task_struct *__prev = (prev);\
struct task_struct *__next = (next);\
-   __switch_to_aux(__prev, __next);\
+   if (has_fpu)\
+   __switch_to_aux(__prev, __next);\
((last) = __switch_to(__prev, __next)); \
 } while (0)
 
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 17011a870044..46942e635266 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -22,6 +22,9 @@
 #include 
 
 unsigned long elf_hwcap __read_mostly;
+#ifdef CONFIG_FPU
+bool has_fpu __read_mostly;
+#endif
 
 void riscv_fill_hwcap(void)
 {
@@ -58,4 +61,9 @@ void riscv_fill_hwcap(void)
elf_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
 
pr_info("elf_hwcap is 0x%lx", elf_hwcap);
+
+#ifdef CONFIG_FPU
+   if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
+   has_fpu = true;
+#endif
 }
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index 07d515655aa9..bef19993ea92 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -76,7 +76,9 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = DEFAULT_SSTATUS;
+   regs->sstatus = SR_SPIE;
+   if (has_fpu)
+   regs->sstatus |= SR_FS_INITIAL;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 2450b824d799..f9b5e7e352ef 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -98,7 +98,8 @@ static long restore_sigcontext(struct pt_regs *regs,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
/* Restore the floating-point state. */
-   err |= restore_fp_state(regs, >sc_fpregs);
+   if (has_fpu)
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -150,7 +151,8 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_fp_state(regs, >sc_fpregs);
+   if (has_fpu)
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.18.0



[PATCH 4/5] Allow to disable FPU support

2018-08-26 Thread Alan Kao
FPU codes have been separated from common part in previous patches.
This patch add the CONFIG_FPU option and some stubs, so that a no-FPU
configuration is allowed.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/Kconfig |  9 +
 arch/riscv/Makefile|  2 +-
 arch/riscv/include/asm/switch_to.h | 10 ++
 arch/riscv/kernel/Makefile |  2 +-
 arch/riscv/kernel/process.c|  4 +++-
 arch/riscv/kernel/signal.c |  5 +
 6 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 4764fdeb4f1f..a29c9c3a3c5d 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -208,6 +208,15 @@ config RISCV_BASE_PMU
 
 endmenu
 
+config FPU
+   bool "FPU support"
+   default y
+   help
+ Say N here if you want to disable all floating-point related procedure
+ in the kernel.
+
+ If you don't know what to do here, say Y.
+
 endmenu
 
 menu "Kernel type"
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 33bd3b4dd926..74dd2ce6110e 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -45,7 +45,7 @@ KBUILD_CFLAGS += -Wall
 riscv-march-$(CONFIG_ARCH_RV32I)   := rv32im
 riscv-march-$(CONFIG_ARCH_RV64I)   := rv64im
 riscv-march-$(CONFIG_RISCV_ISA_A)  := $(riscv-march-y)a
-riscv-march-y  := fd
+riscv-march-$(CONFIG_FPU)  := fd
 riscv-march-$(CONFIG_RISCV_ISA_C)  := $(riscv-march-y)c
 KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
 KBUILD_AFLAGS += -march=$(riscv-march-y)
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index dd6b05bff75b..093050b03543 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -18,6 +18,7 @@
 #include 
 #include 
 
+#ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
 extern void __fstate_restore(struct task_struct *restore_from);
 
@@ -55,6 +56,15 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
+
+#else
+#define fstate_save(task, regs) do { } while (0)
+#define fstate_restore(task, regs) do { } while (0)
+#define __switch_to_aux(__prev, __next) do { } while (0)
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
+#endif
+
 extern struct task_struct *__switch_to(struct task_struct *,
   struct task_struct *);
 
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index bd433efd915e..f13f7f276639 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,7 +13,6 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
-obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
@@ -32,6 +31,7 @@ obj-y += vdso/
 
 CFLAGS_setup.o := -mcmodel=medany
 
+obj-$(CONFIG_FPU)  += fpu.o
 obj-$(CONFIG_SMP)  += smpboot.o
 obj-$(CONFIG_SMP)  += smp.o
 obj-$(CONFIG_MODULES)  += module.o
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index d7c6ca7c95ae..07d515655aa9 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -76,7 +76,7 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
+   regs->sstatus = DEFAULT_SSTATUS;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
@@ -84,12 +84,14 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
 
 void flush_thread(void)
 {
+#ifdef CONFIG_FPU
/*
 * Reset FPU context
 *  frm: round to nearest, ties to even (IEEE default)
 *  fflags: accrued exceptions cleared
 */
memset(>thread.fstate, 0, sizeof(current->thread.fstate));
+#endif
 }
 
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 6a18b9819ead..2450b824d799 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,6 +37,7 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
+#ifdef CONFIG_FPU
 static long restore_fp_state(struct pt_regs *regs,
 union __riscv_fp_state *sc_fpregs)
 {
@@ -85,6 +86,10 @@ static long save_fp_state(struct pt_regs *regs,
 
return err;
 }
+#else
+#define save_fp_state(task, regs) (0)
+#define restore_fp_state(task, regs) (0)
+#endif
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
-- 
2.18.0



[PATCH v7 0/5] riscv: Add support to no-FPU systems

2018-08-26 Thread Alan Kao
This patchset adds an option, CONFIG_FPU, to enable/disable floating-
point procedures.

Kernel's new behavior will be as follows:

* with CONFIG_FPU=y
  All FPU codes are reserved.  If no FPU is found during booting, a
  global flag will be set, and those functions will be bypassed with
  condition check to that flag.

* with CONFIG_FPU=n
  No floating-point instructions in kernel and all related settings
  are excluded.

Changes in v7:
 - Remove "fd" attribute from KBUILD_CFLAGS.

Changes in v6 (PATCH 0005 only):
 - Make the flag checking neater.

Changes in v5:
 - Invert the polarity of checking flag from no_fpu to has_fpu.

Changes in v4:
 - Append a new patch to detect existence of FPU and followups.
 - Add SPDX header to newly created fpu.S.
 - Fix a build error, sorry for that.
 - Fix wording, style, etc.

Changes in v3:
 - Refactor the whole patch into independent ones.

Changes in v2:
 - Various code cleanups and style fixes.


Alan Kao (5):
  Extract FPU context operations from entry.S
  Refactor FPU code in signal setup/return procedures
  Cleanup ISA string setting
  Allow to disable FPU support
  Auto-detect whether a FPU exists

 arch/riscv/Kconfig |   9 +++
 arch/riscv/Makefile|  19 +++---
 arch/riscv/include/asm/switch_to.h |  12 +++-
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/cpufeature.c |   8 +++
 arch/riscv/kernel/entry.S  |  87 ---
 arch/riscv/kernel/fpu.S| 106 +
 arch/riscv/kernel/process.c|   6 +-
 arch/riscv/kernel/signal.c |  75 
 9 files changed, 196 insertions(+), 127 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

-- 
2.18.0



[PATCH 2/5] Refactor FPU code in signal setup/return procedures

2018-08-26 Thread Alan Kao
FPU-related logic is separated from normal signal handling path in
this patch.  Kernel can easily be configured to exclude those procedures
for no-FPU systems.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/kernel/signal.c | 68 +++---
 1 file changed, 41 insertions(+), 27 deletions(-)

diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 718d0c984ef0..6a18b9819ead 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,45 +37,63 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
-static long restore_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long restore_fp_state(struct pt_regs *regs,
+union __riscv_fp_state *sc_fpregs)
 {
long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
err = __copy_from_user(>thread.fstate, state, sizeof(*state));
-   if (likely(!err))
-   fstate_restore(current, regs);
+   if (unlikely(err))
+   return err;
+
+   fstate_restore(current, regs);
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   u32 value;
+
+   err = __get_user(value, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   if (value != 0)
+   return -EINVAL;
+   }
+
return err;
 }
 
-static long save_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long save_fp_state(struct pt_regs *regs,
+ union __riscv_fp_state *sc_fpregs)
 {
+   long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
fstate_save(current, regs);
-   return __copy_to_user(state, >thread.fstate, sizeof(*state));
+   err = __copy_to_user(state, >thread.fstate, sizeof(*state));
+   if (unlikely(err))
+   return err;
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   err = __put_user(0, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   }
+
+   return err;
 }
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
 {
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
-   if (unlikely(err))
-   return err;
/* Restore the floating-point state. */
-   err = restore_d_state(regs, >sc_fpregs.d);
-   if (unlikely(err))
-   return err;
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) {
-   u32 value;
-   err = __get_user(value, >sc_fpregs.q.reserved[i]);
-   if (unlikely(err))
-   break;
-   if (value != 0)
-   return -EINVAL;
-   }
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -124,14 +142,10 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
 {
struct sigcontext __user *sc = >uc.uc_mcontext;
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_d_state(regs, >sc_fpregs.d);
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++)
-   err |= __put_user(0, >sc_fpregs.q.reserved[i]);
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.18.0



[PATCH 5/5] Auto-detect whether a FPU exists

2018-08-26 Thread Alan Kao
We expect that a kernel with CONFIG_FPU=y can still support no-FPU
machines. To do so, the kernel should first examine the existence of a
FPU, then do nothing if a FPU does exist; otherwise, it should
disable/bypass all FPU-related functions.

In this patch, a new global variable, has_fpu, is created and determined
when parsing the hardware capability from device tree during booting.
This variable is used in those FPU-related functions.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/include/asm/switch_to.h | 8 
 arch/riscv/kernel/cpufeature.c | 8 
 arch/riscv/kernel/process.c| 4 +++-
 arch/riscv/kernel/signal.c | 6 --
 4 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index 093050b03543..733559083f24 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -56,13 +56,12 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
-
+extern bool has_fpu;
 #else
+#define has_fpu false
 #define fstate_save(task, regs) do { } while (0)
 #define fstate_restore(task, regs) do { } while (0)
 #define __switch_to_aux(__prev, __next) do { } while (0)
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
 #endif
 
 extern struct task_struct *__switch_to(struct task_struct *,
@@ -72,7 +71,8 @@ extern struct task_struct *__switch_to(struct task_struct *,
 do {   \
struct task_struct *__prev = (prev);\
struct task_struct *__next = (next);\
-   __switch_to_aux(__prev, __next);\
+   if (has_fpu)\
+   __switch_to_aux(__prev, __next);\
((last) = __switch_to(__prev, __next)); \
 } while (0)
 
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 17011a870044..46942e635266 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -22,6 +22,9 @@
 #include 
 
 unsigned long elf_hwcap __read_mostly;
+#ifdef CONFIG_FPU
+bool has_fpu __read_mostly;
+#endif
 
 void riscv_fill_hwcap(void)
 {
@@ -58,4 +61,9 @@ void riscv_fill_hwcap(void)
elf_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
 
pr_info("elf_hwcap is 0x%lx", elf_hwcap);
+
+#ifdef CONFIG_FPU
+   if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
+   has_fpu = true;
+#endif
 }
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index 07d515655aa9..bef19993ea92 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -76,7 +76,9 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = DEFAULT_SSTATUS;
+   regs->sstatus = SR_SPIE;
+   if (has_fpu)
+   regs->sstatus |= SR_FS_INITIAL;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 2450b824d799..f9b5e7e352ef 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -98,7 +98,8 @@ static long restore_sigcontext(struct pt_regs *regs,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
/* Restore the floating-point state. */
-   err |= restore_fp_state(regs, >sc_fpregs);
+   if (has_fpu)
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -150,7 +151,8 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_fp_state(regs, >sc_fpregs);
+   if (has_fpu)
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.18.0



[PATCH 4/5] Allow to disable FPU support

2018-08-26 Thread Alan Kao
FPU codes have been separated from common part in previous patches.
This patch add the CONFIG_FPU option and some stubs, so that a no-FPU
configuration is allowed.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/Kconfig |  9 +
 arch/riscv/Makefile|  2 +-
 arch/riscv/include/asm/switch_to.h | 10 ++
 arch/riscv/kernel/Makefile |  2 +-
 arch/riscv/kernel/process.c|  4 +++-
 arch/riscv/kernel/signal.c |  5 +
 6 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 4764fdeb4f1f..a29c9c3a3c5d 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -208,6 +208,15 @@ config RISCV_BASE_PMU
 
 endmenu
 
+config FPU
+   bool "FPU support"
+   default y
+   help
+ Say N here if you want to disable all floating-point related procedure
+ in the kernel.
+
+ If you don't know what to do here, say Y.
+
 endmenu
 
 menu "Kernel type"
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 33bd3b4dd926..74dd2ce6110e 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -45,7 +45,7 @@ KBUILD_CFLAGS += -Wall
 riscv-march-$(CONFIG_ARCH_RV32I)   := rv32im
 riscv-march-$(CONFIG_ARCH_RV64I)   := rv64im
 riscv-march-$(CONFIG_RISCV_ISA_A)  := $(riscv-march-y)a
-riscv-march-y  := fd
+riscv-march-$(CONFIG_FPU)  := fd
 riscv-march-$(CONFIG_RISCV_ISA_C)  := $(riscv-march-y)c
 KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
 KBUILD_AFLAGS += -march=$(riscv-march-y)
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index dd6b05bff75b..093050b03543 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -18,6 +18,7 @@
 #include 
 #include 
 
+#ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
 extern void __fstate_restore(struct task_struct *restore_from);
 
@@ -55,6 +56,15 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
+
+#else
+#define fstate_save(task, regs) do { } while (0)
+#define fstate_restore(task, regs) do { } while (0)
+#define __switch_to_aux(__prev, __next) do { } while (0)
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
+#endif
+
 extern struct task_struct *__switch_to(struct task_struct *,
   struct task_struct *);
 
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index bd433efd915e..f13f7f276639 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,7 +13,6 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
-obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
@@ -32,6 +31,7 @@ obj-y += vdso/
 
 CFLAGS_setup.o := -mcmodel=medany
 
+obj-$(CONFIG_FPU)  += fpu.o
 obj-$(CONFIG_SMP)  += smpboot.o
 obj-$(CONFIG_SMP)  += smp.o
 obj-$(CONFIG_MODULES)  += module.o
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index d7c6ca7c95ae..07d515655aa9 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -76,7 +76,7 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
+   regs->sstatus = DEFAULT_SSTATUS;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
@@ -84,12 +84,14 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
 
 void flush_thread(void)
 {
+#ifdef CONFIG_FPU
/*
 * Reset FPU context
 *  frm: round to nearest, ties to even (IEEE default)
 *  fflags: accrued exceptions cleared
 */
memset(>thread.fstate, 0, sizeof(current->thread.fstate));
+#endif
 }
 
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 6a18b9819ead..2450b824d799 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,6 +37,7 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
+#ifdef CONFIG_FPU
 static long restore_fp_state(struct pt_regs *regs,
 union __riscv_fp_state *sc_fpregs)
 {
@@ -85,6 +86,10 @@ static long save_fp_state(struct pt_regs *regs,
 
return err;
 }
+#else
+#define save_fp_state(task, regs) (0)
+#define restore_fp_state(task, regs) (0)
+#endif
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
-- 
2.18.0



[PATCH v7 0/5] riscv: Add support to no-FPU systems

2018-08-26 Thread Alan Kao
This patchset adds an option, CONFIG_FPU, to enable/disable floating-
point procedures.

Kernel's new behavior will be as follows:

* with CONFIG_FPU=y
  All FPU codes are reserved.  If no FPU is found during booting, a
  global flag will be set, and those functions will be bypassed with
  condition check to that flag.

* with CONFIG_FPU=n
  No floating-point instructions in kernel and all related settings
  are excluded.

Changes in v7:
 - Remove "fd" attribute from KBUILD_CFLAGS.

Changes in v6 (PATCH 0005 only):
 - Make the flag checking neater.

Changes in v5:
 - Invert the polarity of checking flag from no_fpu to has_fpu.

Changes in v4:
 - Append a new patch to detect existence of FPU and followups.
 - Add SPDX header to newly created fpu.S.
 - Fix a build error, sorry for that.
 - Fix wording, style, etc.

Changes in v3:
 - Refactor the whole patch into independent ones.

Changes in v2:
 - Various code cleanups and style fixes.


Alan Kao (5):
  Extract FPU context operations from entry.S
  Refactor FPU code in signal setup/return procedures
  Cleanup ISA string setting
  Allow to disable FPU support
  Auto-detect whether a FPU exists

 arch/riscv/Kconfig |   9 +++
 arch/riscv/Makefile|  19 +++---
 arch/riscv/include/asm/switch_to.h |  12 +++-
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/cpufeature.c |   8 +++
 arch/riscv/kernel/entry.S  |  87 ---
 arch/riscv/kernel/fpu.S| 106 +
 arch/riscv/kernel/process.c|   6 +-
 arch/riscv/kernel/signal.c |  75 
 9 files changed, 196 insertions(+), 127 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

-- 
2.18.0



[PATCH 2/5] Refactor FPU code in signal setup/return procedures

2018-08-26 Thread Alan Kao
FPU-related logic is separated from normal signal handling path in
this patch.  Kernel can easily be configured to exclude those procedures
for no-FPU systems.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/kernel/signal.c | 68 +++---
 1 file changed, 41 insertions(+), 27 deletions(-)

diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 718d0c984ef0..6a18b9819ead 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,45 +37,63 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
-static long restore_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long restore_fp_state(struct pt_regs *regs,
+union __riscv_fp_state *sc_fpregs)
 {
long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
err = __copy_from_user(>thread.fstate, state, sizeof(*state));
-   if (likely(!err))
-   fstate_restore(current, regs);
+   if (unlikely(err))
+   return err;
+
+   fstate_restore(current, regs);
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   u32 value;
+
+   err = __get_user(value, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   if (value != 0)
+   return -EINVAL;
+   }
+
return err;
 }
 
-static long save_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long save_fp_state(struct pt_regs *regs,
+ union __riscv_fp_state *sc_fpregs)
 {
+   long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
fstate_save(current, regs);
-   return __copy_to_user(state, >thread.fstate, sizeof(*state));
+   err = __copy_to_user(state, >thread.fstate, sizeof(*state));
+   if (unlikely(err))
+   return err;
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   err = __put_user(0, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   }
+
+   return err;
 }
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
 {
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
-   if (unlikely(err))
-   return err;
/* Restore the floating-point state. */
-   err = restore_d_state(regs, >sc_fpregs.d);
-   if (unlikely(err))
-   return err;
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) {
-   u32 value;
-   err = __get_user(value, >sc_fpregs.q.reserved[i]);
-   if (unlikely(err))
-   break;
-   if (value != 0)
-   return -EINVAL;
-   }
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -124,14 +142,10 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
 {
struct sigcontext __user *sc = >uc.uc_mcontext;
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_d_state(regs, >sc_fpregs.d);
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++)
-   err |= __put_user(0, >sc_fpregs.q.reserved[i]);
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.18.0



[PATCH 1/5] Extract FPU context operations from entry.S

2018-08-26 Thread Alan Kao
We move __fstate_save and __fstate_restore to a new source
file, fpu.S.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/entry.S  |  87 --
 arch/riscv/kernel/fpu.S| 106 +
 3 files changed, 107 insertions(+), 87 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index e1274fc03af4..bd433efd915e 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,6 +13,7 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
+obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index fa2c08e3c05e..59c02e2bf739 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -357,93 +357,6 @@ ENTRY(__switch_to)
ret
 ENDPROC(__switch_to)
 
-ENTRY(__fstate_save)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   csrs sstatus, t1
-   frcsr t0
-   fsd f0,  TASK_THREAD_F0_F0(a0)
-   fsd f1,  TASK_THREAD_F1_F0(a0)
-   fsd f2,  TASK_THREAD_F2_F0(a0)
-   fsd f3,  TASK_THREAD_F3_F0(a0)
-   fsd f4,  TASK_THREAD_F4_F0(a0)
-   fsd f5,  TASK_THREAD_F5_F0(a0)
-   fsd f6,  TASK_THREAD_F6_F0(a0)
-   fsd f7,  TASK_THREAD_F7_F0(a0)
-   fsd f8,  TASK_THREAD_F8_F0(a0)
-   fsd f9,  TASK_THREAD_F9_F0(a0)
-   fsd f10, TASK_THREAD_F10_F0(a0)
-   fsd f11, TASK_THREAD_F11_F0(a0)
-   fsd f12, TASK_THREAD_F12_F0(a0)
-   fsd f13, TASK_THREAD_F13_F0(a0)
-   fsd f14, TASK_THREAD_F14_F0(a0)
-   fsd f15, TASK_THREAD_F15_F0(a0)
-   fsd f16, TASK_THREAD_F16_F0(a0)
-   fsd f17, TASK_THREAD_F17_F0(a0)
-   fsd f18, TASK_THREAD_F18_F0(a0)
-   fsd f19, TASK_THREAD_F19_F0(a0)
-   fsd f20, TASK_THREAD_F20_F0(a0)
-   fsd f21, TASK_THREAD_F21_F0(a0)
-   fsd f22, TASK_THREAD_F22_F0(a0)
-   fsd f23, TASK_THREAD_F23_F0(a0)
-   fsd f24, TASK_THREAD_F24_F0(a0)
-   fsd f25, TASK_THREAD_F25_F0(a0)
-   fsd f26, TASK_THREAD_F26_F0(a0)
-   fsd f27, TASK_THREAD_F27_F0(a0)
-   fsd f28, TASK_THREAD_F28_F0(a0)
-   fsd f29, TASK_THREAD_F29_F0(a0)
-   fsd f30, TASK_THREAD_F30_F0(a0)
-   fsd f31, TASK_THREAD_F31_F0(a0)
-   sw t0, TASK_THREAD_FCSR_F0(a0)
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_save)
-
-ENTRY(__fstate_restore)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   lw t0, TASK_THREAD_FCSR_F0(a0)
-   csrs sstatus, t1
-   fld f0,  TASK_THREAD_F0_F0(a0)
-   fld f1,  TASK_THREAD_F1_F0(a0)
-   fld f2,  TASK_THREAD_F2_F0(a0)
-   fld f3,  TASK_THREAD_F3_F0(a0)
-   fld f4,  TASK_THREAD_F4_F0(a0)
-   fld f5,  TASK_THREAD_F5_F0(a0)
-   fld f6,  TASK_THREAD_F6_F0(a0)
-   fld f7,  TASK_THREAD_F7_F0(a0)
-   fld f8,  TASK_THREAD_F8_F0(a0)
-   fld f9,  TASK_THREAD_F9_F0(a0)
-   fld f10, TASK_THREAD_F10_F0(a0)
-   fld f11, TASK_THREAD_F11_F0(a0)
-   fld f12, TASK_THREAD_F12_F0(a0)
-   fld f13, TASK_THREAD_F13_F0(a0)
-   fld f14, TASK_THREAD_F14_F0(a0)
-   fld f15, TASK_THREAD_F15_F0(a0)
-   fld f16, TASK_THREAD_F16_F0(a0)
-   fld f17, TASK_THREAD_F17_F0(a0)
-   fld f18, TASK_THREAD_F18_F0(a0)
-   fld f19, TASK_THREAD_F19_F0(a0)
-   fld f20, TASK_THREAD_F20_F0(a0)
-   fld f21, TASK_THREAD_F21_F0(a0)
-   fld f22, TASK_THREAD_F22_F0(a0)
-   fld f23, TASK_THREAD_F23_F0(a0)
-   fld f24, TASK_THREAD_F24_F0(a0)
-   fld f25, TASK_THREAD_F25_F0(a0)
-   fld f26, TASK_THREAD_F26_F0(a0)
-   fld f27, TASK_THREAD_F27_F0(a0)
-   fld f28, TASK_THREAD_F28_F0(a0)
-   fld f29, TASK_THREAD_F29_F0(a0)
-   fld f30, TASK_THREAD_F30_F0(a0)
-   fld f31, TASK_THREAD_F31_F0(a0)
-   fscsr t0
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_restore)
-
-
.section ".rodata"
/* Exception vector table */
 ENTRY(excp_vect_table)
diff --git a/arch/riscv/kernel/fpu.S b/arch/riscv/kernel/fpu.S
new file mode 100644
index ..1defb0618aff
--- /dev/null
+++ b/arch/riscv/kernel/fpu.S
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2012 Regents of the University of California
+ * Copyright (C) 2017 SiFive
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include 
+

[PATCH 3/5] Cleanup ISA string setting

2018-08-26 Thread Alan Kao
This patch cleanup the MARCH string passing to both compiler and
assembler.  Note that the CFLAGS should not contain "fd" before we
have mechnisms like kernel_fpu_begin/end in other architectures.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/Makefile | 19 ---
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 1f536a7784aa..33bd3b4dd926 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -29,7 +29,6 @@ ifeq ($(CONFIG_ARCH_RV64I),y)

KBUILD_CFLAGS   += $(call cc-ifversion, -ge, 0500, 
-DCONFIG_ARCH_SUPPORTS_INT128)
 
-   KBUILD_MARCH = rv64im
LDFLAGS += -melf64lriscv
 else
BITS := 32
@@ -37,22 +36,20 @@ else
 
KBUILD_CFLAGS += -mabi=ilp32
KBUILD_AFLAGS += -mabi=ilp32
-   KBUILD_MARCH = rv32im
LDFLAGS += -melf32lriscv
 endif
 
 KBUILD_CFLAGS += -Wall
 
-ifeq ($(CONFIG_RISCV_ISA_A),y)
-   KBUILD_ARCH_A = a
-endif
-ifeq ($(CONFIG_RISCV_ISA_C),y)
-   KBUILD_ARCH_C = c
-endif
-
-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+# ISA string setting
+riscv-march-$(CONFIG_ARCH_RV32I)   := rv32im
+riscv-march-$(CONFIG_ARCH_RV64I)   := rv64im
+riscv-march-$(CONFIG_RISCV_ISA_A)  := $(riscv-march-y)a
+riscv-march-y  := fd
+riscv-march-$(CONFIG_RISCV_ISA_C)  := $(riscv-march-y)c
+KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
+KBUILD_AFLAGS += -march=$(riscv-march-y)
 
-KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
 KBUILD_CFLAGS += -mno-save-restore
 KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
 
-- 
2.18.0



[PATCH 1/5] Extract FPU context operations from entry.S

2018-08-26 Thread Alan Kao
We move __fstate_save and __fstate_restore to a new source
file, fpu.S.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/entry.S  |  87 --
 arch/riscv/kernel/fpu.S| 106 +
 3 files changed, 107 insertions(+), 87 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index e1274fc03af4..bd433efd915e 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,6 +13,7 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
+obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index fa2c08e3c05e..59c02e2bf739 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -357,93 +357,6 @@ ENTRY(__switch_to)
ret
 ENDPROC(__switch_to)
 
-ENTRY(__fstate_save)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   csrs sstatus, t1
-   frcsr t0
-   fsd f0,  TASK_THREAD_F0_F0(a0)
-   fsd f1,  TASK_THREAD_F1_F0(a0)
-   fsd f2,  TASK_THREAD_F2_F0(a0)
-   fsd f3,  TASK_THREAD_F3_F0(a0)
-   fsd f4,  TASK_THREAD_F4_F0(a0)
-   fsd f5,  TASK_THREAD_F5_F0(a0)
-   fsd f6,  TASK_THREAD_F6_F0(a0)
-   fsd f7,  TASK_THREAD_F7_F0(a0)
-   fsd f8,  TASK_THREAD_F8_F0(a0)
-   fsd f9,  TASK_THREAD_F9_F0(a0)
-   fsd f10, TASK_THREAD_F10_F0(a0)
-   fsd f11, TASK_THREAD_F11_F0(a0)
-   fsd f12, TASK_THREAD_F12_F0(a0)
-   fsd f13, TASK_THREAD_F13_F0(a0)
-   fsd f14, TASK_THREAD_F14_F0(a0)
-   fsd f15, TASK_THREAD_F15_F0(a0)
-   fsd f16, TASK_THREAD_F16_F0(a0)
-   fsd f17, TASK_THREAD_F17_F0(a0)
-   fsd f18, TASK_THREAD_F18_F0(a0)
-   fsd f19, TASK_THREAD_F19_F0(a0)
-   fsd f20, TASK_THREAD_F20_F0(a0)
-   fsd f21, TASK_THREAD_F21_F0(a0)
-   fsd f22, TASK_THREAD_F22_F0(a0)
-   fsd f23, TASK_THREAD_F23_F0(a0)
-   fsd f24, TASK_THREAD_F24_F0(a0)
-   fsd f25, TASK_THREAD_F25_F0(a0)
-   fsd f26, TASK_THREAD_F26_F0(a0)
-   fsd f27, TASK_THREAD_F27_F0(a0)
-   fsd f28, TASK_THREAD_F28_F0(a0)
-   fsd f29, TASK_THREAD_F29_F0(a0)
-   fsd f30, TASK_THREAD_F30_F0(a0)
-   fsd f31, TASK_THREAD_F31_F0(a0)
-   sw t0, TASK_THREAD_FCSR_F0(a0)
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_save)
-
-ENTRY(__fstate_restore)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   lw t0, TASK_THREAD_FCSR_F0(a0)
-   csrs sstatus, t1
-   fld f0,  TASK_THREAD_F0_F0(a0)
-   fld f1,  TASK_THREAD_F1_F0(a0)
-   fld f2,  TASK_THREAD_F2_F0(a0)
-   fld f3,  TASK_THREAD_F3_F0(a0)
-   fld f4,  TASK_THREAD_F4_F0(a0)
-   fld f5,  TASK_THREAD_F5_F0(a0)
-   fld f6,  TASK_THREAD_F6_F0(a0)
-   fld f7,  TASK_THREAD_F7_F0(a0)
-   fld f8,  TASK_THREAD_F8_F0(a0)
-   fld f9,  TASK_THREAD_F9_F0(a0)
-   fld f10, TASK_THREAD_F10_F0(a0)
-   fld f11, TASK_THREAD_F11_F0(a0)
-   fld f12, TASK_THREAD_F12_F0(a0)
-   fld f13, TASK_THREAD_F13_F0(a0)
-   fld f14, TASK_THREAD_F14_F0(a0)
-   fld f15, TASK_THREAD_F15_F0(a0)
-   fld f16, TASK_THREAD_F16_F0(a0)
-   fld f17, TASK_THREAD_F17_F0(a0)
-   fld f18, TASK_THREAD_F18_F0(a0)
-   fld f19, TASK_THREAD_F19_F0(a0)
-   fld f20, TASK_THREAD_F20_F0(a0)
-   fld f21, TASK_THREAD_F21_F0(a0)
-   fld f22, TASK_THREAD_F22_F0(a0)
-   fld f23, TASK_THREAD_F23_F0(a0)
-   fld f24, TASK_THREAD_F24_F0(a0)
-   fld f25, TASK_THREAD_F25_F0(a0)
-   fld f26, TASK_THREAD_F26_F0(a0)
-   fld f27, TASK_THREAD_F27_F0(a0)
-   fld f28, TASK_THREAD_F28_F0(a0)
-   fld f29, TASK_THREAD_F29_F0(a0)
-   fld f30, TASK_THREAD_F30_F0(a0)
-   fld f31, TASK_THREAD_F31_F0(a0)
-   fscsr t0
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_restore)
-
-
.section ".rodata"
/* Exception vector table */
 ENTRY(excp_vect_table)
diff --git a/arch/riscv/kernel/fpu.S b/arch/riscv/kernel/fpu.S
new file mode 100644
index ..1defb0618aff
--- /dev/null
+++ b/arch/riscv/kernel/fpu.S
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2012 Regents of the University of California
+ * Copyright (C) 2017 SiFive
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include 
+

[PATCH 3/5] Cleanup ISA string setting

2018-08-26 Thread Alan Kao
This patch cleanup the MARCH string passing to both compiler and
assembler.  Note that the CFLAGS should not contain "fd" before we
have mechnisms like kernel_fpu_begin/end in other architectures.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/Makefile | 19 ---
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 1f536a7784aa..33bd3b4dd926 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -29,7 +29,6 @@ ifeq ($(CONFIG_ARCH_RV64I),y)

KBUILD_CFLAGS   += $(call cc-ifversion, -ge, 0500, 
-DCONFIG_ARCH_SUPPORTS_INT128)
 
-   KBUILD_MARCH = rv64im
LDFLAGS += -melf64lriscv
 else
BITS := 32
@@ -37,22 +36,20 @@ else
 
KBUILD_CFLAGS += -mabi=ilp32
KBUILD_AFLAGS += -mabi=ilp32
-   KBUILD_MARCH = rv32im
LDFLAGS += -melf32lriscv
 endif
 
 KBUILD_CFLAGS += -Wall
 
-ifeq ($(CONFIG_RISCV_ISA_A),y)
-   KBUILD_ARCH_A = a
-endif
-ifeq ($(CONFIG_RISCV_ISA_C),y)
-   KBUILD_ARCH_C = c
-endif
-
-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+# ISA string setting
+riscv-march-$(CONFIG_ARCH_RV32I)   := rv32im
+riscv-march-$(CONFIG_ARCH_RV64I)   := rv64im
+riscv-march-$(CONFIG_RISCV_ISA_A)  := $(riscv-march-y)a
+riscv-march-y  := fd
+riscv-march-$(CONFIG_RISCV_ISA_C)  := $(riscv-march-y)c
+KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
+KBUILD_AFLAGS += -march=$(riscv-march-y)
 
-KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
 KBUILD_CFLAGS += -mno-save-restore
 KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
 
-- 
2.18.0



Re: [PATCH v4 3/5] Cleanup ISA string setting

2018-08-20 Thread Alan Kao
On Mon, Aug 20, 2018 at 03:22:55PM -0700, Palmer Dabbelt wrote:
> On Tue, 07 Aug 2018 20:24:43 PDT (-0700), alan...@andestech.com wrote:
> >Just a side note: (Assume that atomic and compressed is on)
> >
> >Before this patch, assembler was always given the riscv64imafdc
> >MARCH string because there are fld/fsd's in entry.S; compiler was
> >always given riscv64imac because kernel doesn't need floating point
> >code generation.  After this, the MARCH string in AFLAGS and CFLAGS
> >become the same.
> >
> >Signed-off-by: Alan Kao 
> >Cc: Greentime Hu 
> >Cc: Vincent Chen 
> >Cc: Zong Li 
> >Cc: Nick Hu 
> >Reviewed-by: Christoph Hellwig 
> >---
> > arch/riscv/Makefile | 19 ---
> > 1 file changed, 8 insertions(+), 11 deletions(-)
> >
> >diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
> >index 6d4a5f6c3f4f..e0fe6790624f 100644
> >--- a/arch/riscv/Makefile
> >+++ b/arch/riscv/Makefile
> >@@ -26,7 +26,6 @@ ifeq ($(CONFIG_ARCH_RV64I),y)
> >
> > KBUILD_CFLAGS += -mabi=lp64
> > KBUILD_AFLAGS += -mabi=lp64
> >-KBUILD_MARCH = rv64im
> > LDFLAGS += -melf64lriscv
> > else
> > BITS := 32
> >@@ -34,22 +33,20 @@ else
> >
> > KBUILD_CFLAGS += -mabi=ilp32
> > KBUILD_AFLAGS += -mabi=ilp32
> >-KBUILD_MARCH = rv32im
> > LDFLAGS += -melf32lriscv
> > endif
> >
> > KBUILD_CFLAGS += -Wall
> >
> >-ifeq ($(CONFIG_RISCV_ISA_A),y)
> >-KBUILD_ARCH_A = a
> >-endif
> >-ifeq ($(CONFIG_RISCV_ISA_C),y)
> >-KBUILD_ARCH_C = c
> >-endif
> >-
> >-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
> >+# ISA string setting
> >+riscv-march-$(CONFIG_ARCH_RV32I):= rv32im
> >+riscv-march-$(CONFIG_ARCH_RV64I):= rv64im
> >+riscv-march-$(CONFIG_RISCV_ISA_A)   := $(riscv-march-y)a
> >+riscv-march-y   := $(riscv-march-y)fd
> >+riscv-march-$(CONFIG_RISCV_ISA_C)   := $(riscv-march-y)c
> >+KBUILD_CFLAGS += -march=$(riscv-march-y)
> >+KBUILD_AFLAGS += -march=$(riscv-march-y)
> >
> >-KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
> 
> We used to have "fd" disabled in KBUILD_CFLAGS because we wanted to ensure
> that any use of floating-point types within the kernel would trigger the
> inclusion of soft-float libraries rather than emitting hardware
> floating-point instructions.  The worry here is that we'd end up corrupting
> the user's floating-point state with the kernel accesses because of the lazy
> save/restore stuff going on.

Thanks for pointing that out.

Just as you said, the use of KBUILD_CFLAGS=*fd* is based on the assumption that
not a single floating-point instruction involves in the kernel, and that might
be wrong.

> I remember at some point it was illegal to use floating-point within the
> kernel, but for some reason I thought that had changed.  I do see a handful
> of references to "float" and "double" in the kernel source, and most of
> references to kernel_fpu_begin() appear to be in SSE-specific stuff.  My one
> worry are the usages in drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c, as
> I can't quickly demonstrate they won't happen.

Empirically, this CFLAGS with *fd* did not cause any trouble to me, but of
course this is not a good statement to support this patch.

Meanwhile, I find a flaw in "[PATCH 4/5] Allow to Disable FPU Support." 
The purpose of this "[PATCH 3/5] Cleanup ISA String" was to make CONFIG_FPU
a switch for the appearance of "fd" in both KBUILD_CFLAGS and KBUILD_ASFLAGS,
but somehow the modification was forgotten.

> 
> If we do this I think we should at least ensure kernel_fpu_{begin,end}() do
> the right thing for RISC-V.  I'd still feel safer telling the C compiler to
> disallow floating-point, though, as I'm a bit paranoid that GCC might go and
> emit a floating-point instruction even when it's not explicitly asked for.
> I just asked Jim, who actually understands GCC, and he said that it'll spill
> to floating-point registers if the cost function determines it's cheaper
> than the stack.  While he thinks that's unlikely, I don't really want to
> rely a GCC cost function for the correctness of our kernel port.

The purpose of this whole patchset was to remove all floating-point-related
logic in kernel space (while remainging FPU systems work as usual), so
implementing the two APIs would be out of scope here.

I suggest that, some people have to provide these APIs if they do need hardware
floating-point calculation in kernel space (kernel or module) in the future.
It seems that we don't need those for 

Re: [PATCH v4 3/5] Cleanup ISA string setting

2018-08-20 Thread Alan Kao
On Mon, Aug 20, 2018 at 03:22:55PM -0700, Palmer Dabbelt wrote:
> On Tue, 07 Aug 2018 20:24:43 PDT (-0700), alan...@andestech.com wrote:
> >Just a side note: (Assume that atomic and compressed is on)
> >
> >Before this patch, assembler was always given the riscv64imafdc
> >MARCH string because there are fld/fsd's in entry.S; compiler was
> >always given riscv64imac because kernel doesn't need floating point
> >code generation.  After this, the MARCH string in AFLAGS and CFLAGS
> >become the same.
> >
> >Signed-off-by: Alan Kao 
> >Cc: Greentime Hu 
> >Cc: Vincent Chen 
> >Cc: Zong Li 
> >Cc: Nick Hu 
> >Reviewed-by: Christoph Hellwig 
> >---
> > arch/riscv/Makefile | 19 ---
> > 1 file changed, 8 insertions(+), 11 deletions(-)
> >
> >diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
> >index 6d4a5f6c3f4f..e0fe6790624f 100644
> >--- a/arch/riscv/Makefile
> >+++ b/arch/riscv/Makefile
> >@@ -26,7 +26,6 @@ ifeq ($(CONFIG_ARCH_RV64I),y)
> >
> > KBUILD_CFLAGS += -mabi=lp64
> > KBUILD_AFLAGS += -mabi=lp64
> >-KBUILD_MARCH = rv64im
> > LDFLAGS += -melf64lriscv
> > else
> > BITS := 32
> >@@ -34,22 +33,20 @@ else
> >
> > KBUILD_CFLAGS += -mabi=ilp32
> > KBUILD_AFLAGS += -mabi=ilp32
> >-KBUILD_MARCH = rv32im
> > LDFLAGS += -melf32lriscv
> > endif
> >
> > KBUILD_CFLAGS += -Wall
> >
> >-ifeq ($(CONFIG_RISCV_ISA_A),y)
> >-KBUILD_ARCH_A = a
> >-endif
> >-ifeq ($(CONFIG_RISCV_ISA_C),y)
> >-KBUILD_ARCH_C = c
> >-endif
> >-
> >-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
> >+# ISA string setting
> >+riscv-march-$(CONFIG_ARCH_RV32I):= rv32im
> >+riscv-march-$(CONFIG_ARCH_RV64I):= rv64im
> >+riscv-march-$(CONFIG_RISCV_ISA_A)   := $(riscv-march-y)a
> >+riscv-march-y   := $(riscv-march-y)fd
> >+riscv-march-$(CONFIG_RISCV_ISA_C)   := $(riscv-march-y)c
> >+KBUILD_CFLAGS += -march=$(riscv-march-y)
> >+KBUILD_AFLAGS += -march=$(riscv-march-y)
> >
> >-KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
> 
> We used to have "fd" disabled in KBUILD_CFLAGS because we wanted to ensure
> that any use of floating-point types within the kernel would trigger the
> inclusion of soft-float libraries rather than emitting hardware
> floating-point instructions.  The worry here is that we'd end up corrupting
> the user's floating-point state with the kernel accesses because of the lazy
> save/restore stuff going on.

Thanks for pointing that out.

Just as you said, the use of KBUILD_CFLAGS=*fd* is based on the assumption that
not a single floating-point instruction involves in the kernel, and that might
be wrong.

> I remember at some point it was illegal to use floating-point within the
> kernel, but for some reason I thought that had changed.  I do see a handful
> of references to "float" and "double" in the kernel source, and most of
> references to kernel_fpu_begin() appear to be in SSE-specific stuff.  My one
> worry are the usages in drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c, as
> I can't quickly demonstrate they won't happen.

Empirically, this CFLAGS with *fd* did not cause any trouble to me, but of
course this is not a good statement to support this patch.

Meanwhile, I find a flaw in "[PATCH 4/5] Allow to Disable FPU Support." 
The purpose of this "[PATCH 3/5] Cleanup ISA String" was to make CONFIG_FPU
a switch for the appearance of "fd" in both KBUILD_CFLAGS and KBUILD_ASFLAGS,
but somehow the modification was forgotten.

> 
> If we do this I think we should at least ensure kernel_fpu_{begin,end}() do
> the right thing for RISC-V.  I'd still feel safer telling the C compiler to
> disallow floating-point, though, as I'm a bit paranoid that GCC might go and
> emit a floating-point instruction even when it's not explicitly asked for.
> I just asked Jim, who actually understands GCC, and he said that it'll spill
> to floating-point registers if the cost function determines it's cheaper
> than the stack.  While he thinks that's unlikely, I don't really want to
> rely a GCC cost function for the correctness of our kernel port.

The purpose of this whole patchset was to remove all floating-point-related
logic in kernel space (while remainging FPU systems work as usual), so
implementing the two APIs would be out of scope here.

I suggest that, some people have to provide these APIs if they do need hardware
floating-point calculation in kernel space (kernel or module) in the future.
It seems that we don't need those for 

[PATCH v6 5/5] Auto-detect whether a FPU exists

2018-08-09 Thread Alan Kao
We expect that a kernel with CONFIG_FPU=y can still support no-FPU
machines. To do so, the kernel should first examine the existence of a
FPU, then do nothing if a FPU does exist; otherwise, it should
disable/bypass all FPU-related functions.

In this patch, a new global variable, has_fpu, is created and determined
when parsing the hardware capability from device tree during booting.
This variable is used in those FPU-related functions.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/include/asm/switch_to.h | 8 
 arch/riscv/kernel/cpufeature.c | 8 
 arch/riscv/kernel/process.c| 4 +++-
 arch/riscv/kernel/signal.c | 6 --
 4 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index 093050b03543..733559083f24 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -56,13 +56,12 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
-
+extern bool has_fpu;
 #else
+#define has_fpu false
 #define fstate_save(task, regs) do { } while (0)
 #define fstate_restore(task, regs) do { } while (0)
 #define __switch_to_aux(__prev, __next) do { } while (0)
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
 #endif
 
 extern struct task_struct *__switch_to(struct task_struct *,
@@ -72,7 +71,8 @@ extern struct task_struct *__switch_to(struct task_struct *,
 do {   \
struct task_struct *__prev = (prev);\
struct task_struct *__next = (next);\
-   __switch_to_aux(__prev, __next);\
+   if (has_fpu)\
+   __switch_to_aux(__prev, __next);\
((last) = __switch_to(__prev, __next)); \
 } while (0)
 
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 17011a870044..46942e635266 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -22,6 +22,9 @@
 #include 
 
 unsigned long elf_hwcap __read_mostly;
+#ifdef CONFIG_FPU
+bool has_fpu __read_mostly;
+#endif
 
 void riscv_fill_hwcap(void)
 {
@@ -58,4 +61,9 @@ void riscv_fill_hwcap(void)
elf_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
 
pr_info("elf_hwcap is 0x%lx", elf_hwcap);
+
+#ifdef CONFIG_FPU
+   if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
+   has_fpu = true;
+#endif
 }
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index 3820d89e2db9..97155aee9e71 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -83,7 +83,9 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = DEFAULT_SSTATUS;
+   regs->sstatus = SR_SPIE;
+   if (has_fpu)
+   regs->sstatus |= SR_FS_INITIAL;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 2450b824d799..f9b5e7e352ef 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -98,7 +98,8 @@ static long restore_sigcontext(struct pt_regs *regs,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
/* Restore the floating-point state. */
-   err |= restore_fp_state(regs, >sc_fpregs);
+   if (has_fpu)
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -150,7 +151,8 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_fp_state(regs, >sc_fpregs);
+   if (has_fpu)
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.18.0



[PATCH v6 5/5] Auto-detect whether a FPU exists

2018-08-09 Thread Alan Kao
We expect that a kernel with CONFIG_FPU=y can still support no-FPU
machines. To do so, the kernel should first examine the existence of a
FPU, then do nothing if a FPU does exist; otherwise, it should
disable/bypass all FPU-related functions.

In this patch, a new global variable, has_fpu, is created and determined
when parsing the hardware capability from device tree during booting.
This variable is used in those FPU-related functions.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/include/asm/switch_to.h | 8 
 arch/riscv/kernel/cpufeature.c | 8 
 arch/riscv/kernel/process.c| 4 +++-
 arch/riscv/kernel/signal.c | 6 --
 4 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index 093050b03543..733559083f24 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -56,13 +56,12 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
-
+extern bool has_fpu;
 #else
+#define has_fpu false
 #define fstate_save(task, regs) do { } while (0)
 #define fstate_restore(task, regs) do { } while (0)
 #define __switch_to_aux(__prev, __next) do { } while (0)
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
 #endif
 
 extern struct task_struct *__switch_to(struct task_struct *,
@@ -72,7 +71,8 @@ extern struct task_struct *__switch_to(struct task_struct *,
 do {   \
struct task_struct *__prev = (prev);\
struct task_struct *__next = (next);\
-   __switch_to_aux(__prev, __next);\
+   if (has_fpu)\
+   __switch_to_aux(__prev, __next);\
((last) = __switch_to(__prev, __next)); \
 } while (0)
 
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 17011a870044..46942e635266 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -22,6 +22,9 @@
 #include 
 
 unsigned long elf_hwcap __read_mostly;
+#ifdef CONFIG_FPU
+bool has_fpu __read_mostly;
+#endif
 
 void riscv_fill_hwcap(void)
 {
@@ -58,4 +61,9 @@ void riscv_fill_hwcap(void)
elf_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
 
pr_info("elf_hwcap is 0x%lx", elf_hwcap);
+
+#ifdef CONFIG_FPU
+   if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
+   has_fpu = true;
+#endif
 }
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index 3820d89e2db9..97155aee9e71 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -83,7 +83,9 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = DEFAULT_SSTATUS;
+   regs->sstatus = SR_SPIE;
+   if (has_fpu)
+   regs->sstatus |= SR_FS_INITIAL;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 2450b824d799..f9b5e7e352ef 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -98,7 +98,8 @@ static long restore_sigcontext(struct pt_regs *regs,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
/* Restore the floating-point state. */
-   err |= restore_fp_state(regs, >sc_fpregs);
+   if (has_fpu)
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -150,7 +151,8 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_fp_state(regs, >sc_fpregs);
+   if (has_fpu)
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.18.0



Re: [PATCH v5 5/5] Auto-detect whether a FPU exists

2018-08-09 Thread Alan Kao
On Thu, Aug 09, 2018 at 12:02:58AM -0700, Christoph Hellwig wrote:
> On Thu, Aug 09, 2018 at 02:43:36PM +0800, Alan Kao wrote:
> > It does look a little bit weird.  Should I send a v6 for this?
> 
> Yes, please resend the series or just this patch.
> 
> I think the hswap.h definition should go away and we should just
> keep the switch_to.h one, even if that means including the header
> in another C file.
> 

It turns out that only cpufeature.c and switch_to.h are affected
by hwcap.h.  As switch_to.h already had extern has_fpu declaration,
the one in hwcap.h is redundant and can be removed safely.

I will resend just this patch, and mark it as v6.


Re: [PATCH v5 5/5] Auto-detect whether a FPU exists

2018-08-09 Thread Alan Kao
On Thu, Aug 09, 2018 at 12:02:58AM -0700, Christoph Hellwig wrote:
> On Thu, Aug 09, 2018 at 02:43:36PM +0800, Alan Kao wrote:
> > It does look a little bit weird.  Should I send a v6 for this?
> 
> Yes, please resend the series or just this patch.
> 
> I think the hswap.h definition should go away and we should just
> keep the switch_to.h one, even if that means including the header
> in another C file.
> 

It turns out that only cpufeature.c and switch_to.h are affected
by hwcap.h.  As switch_to.h already had extern has_fpu declaration,
the one in hwcap.h is redundant and can be removed safely.

I will resend just this patch, and mark it as v6.


Re: [PATCH v5 5/5] Auto-detect whether a FPU exists

2018-08-09 Thread Alan Kao
On Wed, Aug 08, 2018 at 11:31:24PM -0700, Christoph Hellwig wrote:
> >  extern unsigned long elf_hwcap;
> > +extern bool has_fpu;
> >  #endif
> 
> Doesn't this conflict with the !CONFIG_CPU stub in switch_to.h?

switch_to.h did include asm/hwcap.h, but the !CONFIG_FPU stub

+#define has_fpu false

always shows later than

+extern bool has fpu

so actually no warning during compilation.
> 
> It seems like we should only have this definition in one place to start
> with.

It does look a little bit weird.  Should I send a v6 for this?
> 
> Otherwise this looks fine to me:
> 
> Reviewed-by: Christoph Hellwig 
> 

Thanks for all the feedback.

Alan


Re: [PATCH v5 5/5] Auto-detect whether a FPU exists

2018-08-09 Thread Alan Kao
On Wed, Aug 08, 2018 at 11:31:24PM -0700, Christoph Hellwig wrote:
> >  extern unsigned long elf_hwcap;
> > +extern bool has_fpu;
> >  #endif
> 
> Doesn't this conflict with the !CONFIG_CPU stub in switch_to.h?

switch_to.h did include asm/hwcap.h, but the !CONFIG_FPU stub

+#define has_fpu false

always shows later than

+extern bool has fpu

so actually no warning during compilation.
> 
> It seems like we should only have this definition in one place to start
> with.

It does look a little bit weird.  Should I send a v6 for this?
> 
> Otherwise this looks fine to me:
> 
> Reviewed-by: Christoph Hellwig 
> 

Thanks for all the feedback.

Alan


[PATCH v5 5/5] Auto-detect whether a FPU exists

2018-08-09 Thread Alan Kao
We expect that a kernel with CONFIG_FPU=y can still support no-FPU
machines. To do so, the kernel should first examine the existence of a
FPU, then do nothing if a FPU does exist; otherwise, it should
disable/bypass all FPU-related functions.

In this patch, a new global variable, has_fpu, is created and determined
when parsing the hardware capability from device tree during booting.
This variable is used in those FPU-related functions.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/include/asm/hwcap.h | 1 +
 arch/riscv/include/asm/switch_to.h | 9 +
 arch/riscv/kernel/cpufeature.c | 8 
 arch/riscv/kernel/process.c| 4 +++-
 arch/riscv/kernel/signal.c | 6 --
 5 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
index 8a4ed7bbcbea..b0da2cbfb468 100644
--- a/arch/riscv/include/asm/hwcap.h
+++ b/arch/riscv/include/asm/hwcap.h
@@ -33,5 +33,6 @@ enum {
 };
 
 extern unsigned long elf_hwcap;
+extern bool has_fpu;
 #endif
 #endif
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index 093050b03543..7943f991bd86 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
@@ -56,13 +57,12 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
-
+extern bool has_fpu;
 #else
+#define has_fpu false
 #define fstate_save(task, regs) do { } while (0)
 #define fstate_restore(task, regs) do { } while (0)
 #define __switch_to_aux(__prev, __next) do { } while (0)
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
 #endif
 
 extern struct task_struct *__switch_to(struct task_struct *,
@@ -72,7 +72,8 @@ extern struct task_struct *__switch_to(struct task_struct *,
 do {   \
struct task_struct *__prev = (prev);\
struct task_struct *__next = (next);\
-   __switch_to_aux(__prev, __next);\
+   if (has_fpu)\
+   __switch_to_aux(__prev, __next);\
((last) = __switch_to(__prev, __next)); \
 } while (0)
 
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 17011a870044..46942e635266 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -22,6 +22,9 @@
 #include 
 
 unsigned long elf_hwcap __read_mostly;
+#ifdef CONFIG_FPU
+bool has_fpu __read_mostly;
+#endif
 
 void riscv_fill_hwcap(void)
 {
@@ -58,4 +61,9 @@ void riscv_fill_hwcap(void)
elf_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
 
pr_info("elf_hwcap is 0x%lx", elf_hwcap);
+
+#ifdef CONFIG_FPU
+   if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
+   has_fpu = true;
+#endif
 }
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index 3820d89e2db9..97155aee9e71 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -83,7 +83,9 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = DEFAULT_SSTATUS;
+   regs->sstatus = SR_SPIE;
+   if (has_fpu)
+   regs->sstatus |= SR_FS_INITIAL;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 2450b824d799..f9b5e7e352ef 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -98,7 +98,8 @@ static long restore_sigcontext(struct pt_regs *regs,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
/* Restore the floating-point state. */
-   err |= restore_fp_state(regs, >sc_fpregs);
+   if (has_fpu)
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -150,7 +151,8 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_fp_state(regs, >sc_fpregs);
+   if (has_fpu)
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.18.0



[PATCH v5 5/5] Auto-detect whether a FPU exists

2018-08-09 Thread Alan Kao
We expect that a kernel with CONFIG_FPU=y can still support no-FPU
machines. To do so, the kernel should first examine the existence of a
FPU, then do nothing if a FPU does exist; otherwise, it should
disable/bypass all FPU-related functions.

In this patch, a new global variable, has_fpu, is created and determined
when parsing the hardware capability from device tree during booting.
This variable is used in those FPU-related functions.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/include/asm/hwcap.h | 1 +
 arch/riscv/include/asm/switch_to.h | 9 +
 arch/riscv/kernel/cpufeature.c | 8 
 arch/riscv/kernel/process.c| 4 +++-
 arch/riscv/kernel/signal.c | 6 --
 5 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
index 8a4ed7bbcbea..b0da2cbfb468 100644
--- a/arch/riscv/include/asm/hwcap.h
+++ b/arch/riscv/include/asm/hwcap.h
@@ -33,5 +33,6 @@ enum {
 };
 
 extern unsigned long elf_hwcap;
+extern bool has_fpu;
 #endif
 #endif
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index 093050b03543..7943f991bd86 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
@@ -56,13 +57,12 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
-
+extern bool has_fpu;
 #else
+#define has_fpu false
 #define fstate_save(task, regs) do { } while (0)
 #define fstate_restore(task, regs) do { } while (0)
 #define __switch_to_aux(__prev, __next) do { } while (0)
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
 #endif
 
 extern struct task_struct *__switch_to(struct task_struct *,
@@ -72,7 +72,8 @@ extern struct task_struct *__switch_to(struct task_struct *,
 do {   \
struct task_struct *__prev = (prev);\
struct task_struct *__next = (next);\
-   __switch_to_aux(__prev, __next);\
+   if (has_fpu)\
+   __switch_to_aux(__prev, __next);\
((last) = __switch_to(__prev, __next)); \
 } while (0)
 
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 17011a870044..46942e635266 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -22,6 +22,9 @@
 #include 
 
 unsigned long elf_hwcap __read_mostly;
+#ifdef CONFIG_FPU
+bool has_fpu __read_mostly;
+#endif
 
 void riscv_fill_hwcap(void)
 {
@@ -58,4 +61,9 @@ void riscv_fill_hwcap(void)
elf_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
 
pr_info("elf_hwcap is 0x%lx", elf_hwcap);
+
+#ifdef CONFIG_FPU
+   if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
+   has_fpu = true;
+#endif
 }
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index 3820d89e2db9..97155aee9e71 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -83,7 +83,9 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = DEFAULT_SSTATUS;
+   regs->sstatus = SR_SPIE;
+   if (has_fpu)
+   regs->sstatus |= SR_FS_INITIAL;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 2450b824d799..f9b5e7e352ef 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -98,7 +98,8 @@ static long restore_sigcontext(struct pt_regs *regs,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
/* Restore the floating-point state. */
-   err |= restore_fp_state(regs, >sc_fpregs);
+   if (has_fpu)
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -150,7 +151,8 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_fp_state(regs, >sc_fpregs);
+   if (has_fpu)
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.18.0



[PATCH v5 1/5] Extract FPU context operations from entry.S

2018-08-09 Thread Alan Kao
We move __fstate_save and __fstate_restore to a new source
file, fpu.S.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/entry.S  |  87 --
 arch/riscv/kernel/fpu.S| 106 +
 3 files changed, 107 insertions(+), 87 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index e1274fc03af4..bd433efd915e 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,6 +13,7 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
+obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index 9aaf6c986771..edcd5920ee4e 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -357,93 +357,6 @@ ENTRY(__switch_to)
ret
 ENDPROC(__switch_to)
 
-ENTRY(__fstate_save)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   csrs sstatus, t1
-   frcsr t0
-   fsd f0,  TASK_THREAD_F0_F0(a0)
-   fsd f1,  TASK_THREAD_F1_F0(a0)
-   fsd f2,  TASK_THREAD_F2_F0(a0)
-   fsd f3,  TASK_THREAD_F3_F0(a0)
-   fsd f4,  TASK_THREAD_F4_F0(a0)
-   fsd f5,  TASK_THREAD_F5_F0(a0)
-   fsd f6,  TASK_THREAD_F6_F0(a0)
-   fsd f7,  TASK_THREAD_F7_F0(a0)
-   fsd f8,  TASK_THREAD_F8_F0(a0)
-   fsd f9,  TASK_THREAD_F9_F0(a0)
-   fsd f10, TASK_THREAD_F10_F0(a0)
-   fsd f11, TASK_THREAD_F11_F0(a0)
-   fsd f12, TASK_THREAD_F12_F0(a0)
-   fsd f13, TASK_THREAD_F13_F0(a0)
-   fsd f14, TASK_THREAD_F14_F0(a0)
-   fsd f15, TASK_THREAD_F15_F0(a0)
-   fsd f16, TASK_THREAD_F16_F0(a0)
-   fsd f17, TASK_THREAD_F17_F0(a0)
-   fsd f18, TASK_THREAD_F18_F0(a0)
-   fsd f19, TASK_THREAD_F19_F0(a0)
-   fsd f20, TASK_THREAD_F20_F0(a0)
-   fsd f21, TASK_THREAD_F21_F0(a0)
-   fsd f22, TASK_THREAD_F22_F0(a0)
-   fsd f23, TASK_THREAD_F23_F0(a0)
-   fsd f24, TASK_THREAD_F24_F0(a0)
-   fsd f25, TASK_THREAD_F25_F0(a0)
-   fsd f26, TASK_THREAD_F26_F0(a0)
-   fsd f27, TASK_THREAD_F27_F0(a0)
-   fsd f28, TASK_THREAD_F28_F0(a0)
-   fsd f29, TASK_THREAD_F29_F0(a0)
-   fsd f30, TASK_THREAD_F30_F0(a0)
-   fsd f31, TASK_THREAD_F31_F0(a0)
-   sw t0, TASK_THREAD_FCSR_F0(a0)
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_save)
-
-ENTRY(__fstate_restore)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   lw t0, TASK_THREAD_FCSR_F0(a0)
-   csrs sstatus, t1
-   fld f0,  TASK_THREAD_F0_F0(a0)
-   fld f1,  TASK_THREAD_F1_F0(a0)
-   fld f2,  TASK_THREAD_F2_F0(a0)
-   fld f3,  TASK_THREAD_F3_F0(a0)
-   fld f4,  TASK_THREAD_F4_F0(a0)
-   fld f5,  TASK_THREAD_F5_F0(a0)
-   fld f6,  TASK_THREAD_F6_F0(a0)
-   fld f7,  TASK_THREAD_F7_F0(a0)
-   fld f8,  TASK_THREAD_F8_F0(a0)
-   fld f9,  TASK_THREAD_F9_F0(a0)
-   fld f10, TASK_THREAD_F10_F0(a0)
-   fld f11, TASK_THREAD_F11_F0(a0)
-   fld f12, TASK_THREAD_F12_F0(a0)
-   fld f13, TASK_THREAD_F13_F0(a0)
-   fld f14, TASK_THREAD_F14_F0(a0)
-   fld f15, TASK_THREAD_F15_F0(a0)
-   fld f16, TASK_THREAD_F16_F0(a0)
-   fld f17, TASK_THREAD_F17_F0(a0)
-   fld f18, TASK_THREAD_F18_F0(a0)
-   fld f19, TASK_THREAD_F19_F0(a0)
-   fld f20, TASK_THREAD_F20_F0(a0)
-   fld f21, TASK_THREAD_F21_F0(a0)
-   fld f22, TASK_THREAD_F22_F0(a0)
-   fld f23, TASK_THREAD_F23_F0(a0)
-   fld f24, TASK_THREAD_F24_F0(a0)
-   fld f25, TASK_THREAD_F25_F0(a0)
-   fld f26, TASK_THREAD_F26_F0(a0)
-   fld f27, TASK_THREAD_F27_F0(a0)
-   fld f28, TASK_THREAD_F28_F0(a0)
-   fld f29, TASK_THREAD_F29_F0(a0)
-   fld f30, TASK_THREAD_F30_F0(a0)
-   fld f31, TASK_THREAD_F31_F0(a0)
-   fscsr t0
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_restore)
-
-
.section ".rodata"
/* Exception vector table */
 ENTRY(excp_vect_table)
diff --git a/arch/riscv/kernel/fpu.S b/arch/riscv/kernel/fpu.S
new file mode 100644
index ..1defb0618aff
--- /dev/null
+++ b/arch/riscv/kernel/fpu.S
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2012 Regents of the University of California
+ * Copyright (C) 2017 SiFive
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include 
+

[PATCH v5 0/5] riscv: Add support to no-FPU systems

2018-08-09 Thread Alan Kao
This patchset adds an option, CONFIG_FPU, to enable/disable floating-
point procedures.

Kernel's new behavior will be as follows:

* with CONFIG_FPU=y
  All FPU codes are reserved.  If no FPU is found during booting, a
  global flag will be set, and those functions will be bypassed with
  condition check to that flag.

* with CONFIG_FPU=n
  No floating-point instructions in kernel and all related settings
  are excluded.

Changes in v5:
 - Invert the polarity of checking flag from no_fpu to has_fpu.

Changes in v4:
 - Append a new patch to detect existence of FPU and followups.
 - Add SPDX header to newly created fpu.S.
 - Fix a build error, sorry for that.
 - Fix wording, style, etc.

Changes in v3:
 - Refactor the whole patch into independent ones.

Changes in v2:
 - Various code cleanups and style fixes.

Alan Kao (5):
  Extract FPU context operations from entry.S
  Refactor FPU code in signal setup/return procedures
  Cleanup ISA string setting
  Allow to disable FPU support
  Auto-detect whether a FPU exists

 arch/riscv/Kconfig |   9 +++
 arch/riscv/Makefile|  19 +++---
 arch/riscv/include/asm/hwcap.h |   1 +
 arch/riscv/include/asm/switch_to.h |  13 +++-
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/cpufeature.c |   8 +++
 arch/riscv/kernel/entry.S  |  87 ---
 arch/riscv/kernel/fpu.S| 106 +
 arch/riscv/kernel/process.c|   6 +-
 arch/riscv/kernel/signal.c |  75 
 10 files changed, 198 insertions(+), 127 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

-- 
2.18.0



[PATCH v5 4/5] Allow to disable FPU support

2018-08-09 Thread Alan Kao
FPU codes have been separated from common part in previous patches.
This patch add the CONFIG_FPU option and some stubs, so that a no-FPU
configuration is allowed.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/Kconfig |  9 +
 arch/riscv/include/asm/switch_to.h | 10 ++
 arch/riscv/kernel/Makefile |  2 +-
 arch/riscv/kernel/process.c|  4 +++-
 arch/riscv/kernel/signal.c |  5 +
 5 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 6debcc4afc72..6069597ba73f 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -232,6 +232,15 @@ config RISCV_BASE_PMU
 
 endmenu
 
+config FPU
+   bool "FPU support"
+   default y
+   help
+ Say N here if you want to disable all floating-point related procedure
+ in the kernel.
+
+ If you don't know what to do here, say Y.
+
 endmenu
 
 menu "Kernel type"
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index dd6b05bff75b..093050b03543 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -18,6 +18,7 @@
 #include 
 #include 
 
+#ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
 extern void __fstate_restore(struct task_struct *restore_from);
 
@@ -55,6 +56,15 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
+
+#else
+#define fstate_save(task, regs) do { } while (0)
+#define fstate_restore(task, regs) do { } while (0)
+#define __switch_to_aux(__prev, __next) do { } while (0)
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
+#endif
+
 extern struct task_struct *__switch_to(struct task_struct *,
   struct task_struct *);
 
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index bd433efd915e..f13f7f276639 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,7 +13,6 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
-obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
@@ -32,6 +31,7 @@ obj-y += vdso/
 
 CFLAGS_setup.o := -mcmodel=medany
 
+obj-$(CONFIG_FPU)  += fpu.o
 obj-$(CONFIG_SMP)  += smpboot.o
 obj-$(CONFIG_SMP)  += smp.o
 obj-$(CONFIG_MODULES)  += module.o
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index cb209139ba53..3820d89e2db9 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -83,7 +83,7 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
+   regs->sstatus = DEFAULT_SSTATUS;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
@@ -91,12 +91,14 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
 
 void flush_thread(void)
 {
+#ifdef CONFIG_FPU
/*
 * Reset FPU context
 *  frm: round to nearest, ties to even (IEEE default)
 *  fflags: accrued exceptions cleared
 */
memset(>thread.fstate, 0, sizeof(current->thread.fstate));
+#endif
 }
 
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 6a18b9819ead..2450b824d799 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,6 +37,7 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
+#ifdef CONFIG_FPU
 static long restore_fp_state(struct pt_regs *regs,
 union __riscv_fp_state *sc_fpregs)
 {
@@ -85,6 +86,10 @@ static long save_fp_state(struct pt_regs *regs,
 
return err;
 }
+#else
+#define save_fp_state(task, regs) (0)
+#define restore_fp_state(task, regs) (0)
+#endif
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
-- 
2.18.0



[PATCH v5 2/5] Refactor FPU code in signal setup/return procedures

2018-08-09 Thread Alan Kao
FPU-related logic is separated from normal signal handling path in
this patch.  Kernel can easily be configured to exclude those procedures
for no-FPU systems.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/kernel/signal.c | 68 +++---
 1 file changed, 41 insertions(+), 27 deletions(-)

diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 718d0c984ef0..6a18b9819ead 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,45 +37,63 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
-static long restore_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long restore_fp_state(struct pt_regs *regs,
+union __riscv_fp_state *sc_fpregs)
 {
long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
err = __copy_from_user(>thread.fstate, state, sizeof(*state));
-   if (likely(!err))
-   fstate_restore(current, regs);
+   if (unlikely(err))
+   return err;
+
+   fstate_restore(current, regs);
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   u32 value;
+
+   err = __get_user(value, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   if (value != 0)
+   return -EINVAL;
+   }
+
return err;
 }
 
-static long save_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long save_fp_state(struct pt_regs *regs,
+ union __riscv_fp_state *sc_fpregs)
 {
+   long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
fstate_save(current, regs);
-   return __copy_to_user(state, >thread.fstate, sizeof(*state));
+   err = __copy_to_user(state, >thread.fstate, sizeof(*state));
+   if (unlikely(err))
+   return err;
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   err = __put_user(0, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   }
+
+   return err;
 }
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
 {
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
-   if (unlikely(err))
-   return err;
/* Restore the floating-point state. */
-   err = restore_d_state(regs, >sc_fpregs.d);
-   if (unlikely(err))
-   return err;
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) {
-   u32 value;
-   err = __get_user(value, >sc_fpregs.q.reserved[i]);
-   if (unlikely(err))
-   break;
-   if (value != 0)
-   return -EINVAL;
-   }
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -124,14 +142,10 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
 {
struct sigcontext __user *sc = >uc.uc_mcontext;
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_d_state(regs, >sc_fpregs.d);
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++)
-   err |= __put_user(0, >sc_fpregs.q.reserved[i]);
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.18.0



[PATCH v5 3/5] Cleanup ISA string setting

2018-08-09 Thread Alan Kao
Just a side note: (Assume that atomic and compressed is on)

Before this patch, assembler was always given the riscv64imafdc
MARCH string because there are fld/fsd's in entry.S; compiler was
always given riscv64imac because kernel doesn't need floating point
code generation.  After this, the MARCH string in AFLAGS and CFLAGS
become the same.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/Makefile | 19 ---
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 6d4a5f6c3f4f..e0fe6790624f 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -26,7 +26,6 @@ ifeq ($(CONFIG_ARCH_RV64I),y)
 
KBUILD_CFLAGS += -mabi=lp64
KBUILD_AFLAGS += -mabi=lp64
-   KBUILD_MARCH = rv64im
LDFLAGS += -melf64lriscv
 else
BITS := 32
@@ -34,22 +33,20 @@ else
 
KBUILD_CFLAGS += -mabi=ilp32
KBUILD_AFLAGS += -mabi=ilp32
-   KBUILD_MARCH = rv32im
LDFLAGS += -melf32lriscv
 endif
 
 KBUILD_CFLAGS += -Wall
 
-ifeq ($(CONFIG_RISCV_ISA_A),y)
-   KBUILD_ARCH_A = a
-endif
-ifeq ($(CONFIG_RISCV_ISA_C),y)
-   KBUILD_ARCH_C = c
-endif
-
-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+# ISA string setting
+riscv-march-$(CONFIG_ARCH_RV32I)   := rv32im
+riscv-march-$(CONFIG_ARCH_RV64I)   := rv64im
+riscv-march-$(CONFIG_RISCV_ISA_A)  := $(riscv-march-y)a
+riscv-march-y  := $(riscv-march-y)fd
+riscv-march-$(CONFIG_RISCV_ISA_C)  := $(riscv-march-y)c
+KBUILD_CFLAGS += -march=$(riscv-march-y)
+KBUILD_AFLAGS += -march=$(riscv-march-y)
 
-KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
 KBUILD_CFLAGS += -mno-save-restore
 KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
 
-- 
2.18.0



[PATCH v5 4/5] Allow to disable FPU support

2018-08-09 Thread Alan Kao
FPU codes have been separated from common part in previous patches.
This patch add the CONFIG_FPU option and some stubs, so that a no-FPU
configuration is allowed.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/Kconfig |  9 +
 arch/riscv/include/asm/switch_to.h | 10 ++
 arch/riscv/kernel/Makefile |  2 +-
 arch/riscv/kernel/process.c|  4 +++-
 arch/riscv/kernel/signal.c |  5 +
 5 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 6debcc4afc72..6069597ba73f 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -232,6 +232,15 @@ config RISCV_BASE_PMU
 
 endmenu
 
+config FPU
+   bool "FPU support"
+   default y
+   help
+ Say N here if you want to disable all floating-point related procedure
+ in the kernel.
+
+ If you don't know what to do here, say Y.
+
 endmenu
 
 menu "Kernel type"
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index dd6b05bff75b..093050b03543 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -18,6 +18,7 @@
 #include 
 #include 
 
+#ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
 extern void __fstate_restore(struct task_struct *restore_from);
 
@@ -55,6 +56,15 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
+
+#else
+#define fstate_save(task, regs) do { } while (0)
+#define fstate_restore(task, regs) do { } while (0)
+#define __switch_to_aux(__prev, __next) do { } while (0)
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
+#endif
+
 extern struct task_struct *__switch_to(struct task_struct *,
   struct task_struct *);
 
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index bd433efd915e..f13f7f276639 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,7 +13,6 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
-obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
@@ -32,6 +31,7 @@ obj-y += vdso/
 
 CFLAGS_setup.o := -mcmodel=medany
 
+obj-$(CONFIG_FPU)  += fpu.o
 obj-$(CONFIG_SMP)  += smpboot.o
 obj-$(CONFIG_SMP)  += smp.o
 obj-$(CONFIG_MODULES)  += module.o
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index cb209139ba53..3820d89e2db9 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -83,7 +83,7 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
+   regs->sstatus = DEFAULT_SSTATUS;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
@@ -91,12 +91,14 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
 
 void flush_thread(void)
 {
+#ifdef CONFIG_FPU
/*
 * Reset FPU context
 *  frm: round to nearest, ties to even (IEEE default)
 *  fflags: accrued exceptions cleared
 */
memset(>thread.fstate, 0, sizeof(current->thread.fstate));
+#endif
 }
 
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 6a18b9819ead..2450b824d799 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,6 +37,7 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
+#ifdef CONFIG_FPU
 static long restore_fp_state(struct pt_regs *regs,
 union __riscv_fp_state *sc_fpregs)
 {
@@ -85,6 +86,10 @@ static long save_fp_state(struct pt_regs *regs,
 
return err;
 }
+#else
+#define save_fp_state(task, regs) (0)
+#define restore_fp_state(task, regs) (0)
+#endif
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
-- 
2.18.0



[PATCH v5 2/5] Refactor FPU code in signal setup/return procedures

2018-08-09 Thread Alan Kao
FPU-related logic is separated from normal signal handling path in
this patch.  Kernel can easily be configured to exclude those procedures
for no-FPU systems.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/kernel/signal.c | 68 +++---
 1 file changed, 41 insertions(+), 27 deletions(-)

diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 718d0c984ef0..6a18b9819ead 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,45 +37,63 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
-static long restore_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long restore_fp_state(struct pt_regs *regs,
+union __riscv_fp_state *sc_fpregs)
 {
long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
err = __copy_from_user(>thread.fstate, state, sizeof(*state));
-   if (likely(!err))
-   fstate_restore(current, regs);
+   if (unlikely(err))
+   return err;
+
+   fstate_restore(current, regs);
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   u32 value;
+
+   err = __get_user(value, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   if (value != 0)
+   return -EINVAL;
+   }
+
return err;
 }
 
-static long save_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long save_fp_state(struct pt_regs *regs,
+ union __riscv_fp_state *sc_fpregs)
 {
+   long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
fstate_save(current, regs);
-   return __copy_to_user(state, >thread.fstate, sizeof(*state));
+   err = __copy_to_user(state, >thread.fstate, sizeof(*state));
+   if (unlikely(err))
+   return err;
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   err = __put_user(0, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   }
+
+   return err;
 }
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
 {
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
-   if (unlikely(err))
-   return err;
/* Restore the floating-point state. */
-   err = restore_d_state(regs, >sc_fpregs.d);
-   if (unlikely(err))
-   return err;
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) {
-   u32 value;
-   err = __get_user(value, >sc_fpregs.q.reserved[i]);
-   if (unlikely(err))
-   break;
-   if (value != 0)
-   return -EINVAL;
-   }
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -124,14 +142,10 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
 {
struct sigcontext __user *sc = >uc.uc_mcontext;
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_d_state(regs, >sc_fpregs.d);
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++)
-   err |= __put_user(0, >sc_fpregs.q.reserved[i]);
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.18.0



[PATCH v5 3/5] Cleanup ISA string setting

2018-08-09 Thread Alan Kao
Just a side note: (Assume that atomic and compressed is on)

Before this patch, assembler was always given the riscv64imafdc
MARCH string because there are fld/fsd's in entry.S; compiler was
always given riscv64imac because kernel doesn't need floating point
code generation.  After this, the MARCH string in AFLAGS and CFLAGS
become the same.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/Makefile | 19 ---
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 6d4a5f6c3f4f..e0fe6790624f 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -26,7 +26,6 @@ ifeq ($(CONFIG_ARCH_RV64I),y)
 
KBUILD_CFLAGS += -mabi=lp64
KBUILD_AFLAGS += -mabi=lp64
-   KBUILD_MARCH = rv64im
LDFLAGS += -melf64lriscv
 else
BITS := 32
@@ -34,22 +33,20 @@ else
 
KBUILD_CFLAGS += -mabi=ilp32
KBUILD_AFLAGS += -mabi=ilp32
-   KBUILD_MARCH = rv32im
LDFLAGS += -melf32lriscv
 endif
 
 KBUILD_CFLAGS += -Wall
 
-ifeq ($(CONFIG_RISCV_ISA_A),y)
-   KBUILD_ARCH_A = a
-endif
-ifeq ($(CONFIG_RISCV_ISA_C),y)
-   KBUILD_ARCH_C = c
-endif
-
-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+# ISA string setting
+riscv-march-$(CONFIG_ARCH_RV32I)   := rv32im
+riscv-march-$(CONFIG_ARCH_RV64I)   := rv64im
+riscv-march-$(CONFIG_RISCV_ISA_A)  := $(riscv-march-y)a
+riscv-march-y  := $(riscv-march-y)fd
+riscv-march-$(CONFIG_RISCV_ISA_C)  := $(riscv-march-y)c
+KBUILD_CFLAGS += -march=$(riscv-march-y)
+KBUILD_AFLAGS += -march=$(riscv-march-y)
 
-KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
 KBUILD_CFLAGS += -mno-save-restore
 KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
 
-- 
2.18.0



[PATCH v5 1/5] Extract FPU context operations from entry.S

2018-08-09 Thread Alan Kao
We move __fstate_save and __fstate_restore to a new source
file, fpu.S.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/entry.S  |  87 --
 arch/riscv/kernel/fpu.S| 106 +
 3 files changed, 107 insertions(+), 87 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index e1274fc03af4..bd433efd915e 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,6 +13,7 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
+obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index 9aaf6c986771..edcd5920ee4e 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -357,93 +357,6 @@ ENTRY(__switch_to)
ret
 ENDPROC(__switch_to)
 
-ENTRY(__fstate_save)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   csrs sstatus, t1
-   frcsr t0
-   fsd f0,  TASK_THREAD_F0_F0(a0)
-   fsd f1,  TASK_THREAD_F1_F0(a0)
-   fsd f2,  TASK_THREAD_F2_F0(a0)
-   fsd f3,  TASK_THREAD_F3_F0(a0)
-   fsd f4,  TASK_THREAD_F4_F0(a0)
-   fsd f5,  TASK_THREAD_F5_F0(a0)
-   fsd f6,  TASK_THREAD_F6_F0(a0)
-   fsd f7,  TASK_THREAD_F7_F0(a0)
-   fsd f8,  TASK_THREAD_F8_F0(a0)
-   fsd f9,  TASK_THREAD_F9_F0(a0)
-   fsd f10, TASK_THREAD_F10_F0(a0)
-   fsd f11, TASK_THREAD_F11_F0(a0)
-   fsd f12, TASK_THREAD_F12_F0(a0)
-   fsd f13, TASK_THREAD_F13_F0(a0)
-   fsd f14, TASK_THREAD_F14_F0(a0)
-   fsd f15, TASK_THREAD_F15_F0(a0)
-   fsd f16, TASK_THREAD_F16_F0(a0)
-   fsd f17, TASK_THREAD_F17_F0(a0)
-   fsd f18, TASK_THREAD_F18_F0(a0)
-   fsd f19, TASK_THREAD_F19_F0(a0)
-   fsd f20, TASK_THREAD_F20_F0(a0)
-   fsd f21, TASK_THREAD_F21_F0(a0)
-   fsd f22, TASK_THREAD_F22_F0(a0)
-   fsd f23, TASK_THREAD_F23_F0(a0)
-   fsd f24, TASK_THREAD_F24_F0(a0)
-   fsd f25, TASK_THREAD_F25_F0(a0)
-   fsd f26, TASK_THREAD_F26_F0(a0)
-   fsd f27, TASK_THREAD_F27_F0(a0)
-   fsd f28, TASK_THREAD_F28_F0(a0)
-   fsd f29, TASK_THREAD_F29_F0(a0)
-   fsd f30, TASK_THREAD_F30_F0(a0)
-   fsd f31, TASK_THREAD_F31_F0(a0)
-   sw t0, TASK_THREAD_FCSR_F0(a0)
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_save)
-
-ENTRY(__fstate_restore)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   lw t0, TASK_THREAD_FCSR_F0(a0)
-   csrs sstatus, t1
-   fld f0,  TASK_THREAD_F0_F0(a0)
-   fld f1,  TASK_THREAD_F1_F0(a0)
-   fld f2,  TASK_THREAD_F2_F0(a0)
-   fld f3,  TASK_THREAD_F3_F0(a0)
-   fld f4,  TASK_THREAD_F4_F0(a0)
-   fld f5,  TASK_THREAD_F5_F0(a0)
-   fld f6,  TASK_THREAD_F6_F0(a0)
-   fld f7,  TASK_THREAD_F7_F0(a0)
-   fld f8,  TASK_THREAD_F8_F0(a0)
-   fld f9,  TASK_THREAD_F9_F0(a0)
-   fld f10, TASK_THREAD_F10_F0(a0)
-   fld f11, TASK_THREAD_F11_F0(a0)
-   fld f12, TASK_THREAD_F12_F0(a0)
-   fld f13, TASK_THREAD_F13_F0(a0)
-   fld f14, TASK_THREAD_F14_F0(a0)
-   fld f15, TASK_THREAD_F15_F0(a0)
-   fld f16, TASK_THREAD_F16_F0(a0)
-   fld f17, TASK_THREAD_F17_F0(a0)
-   fld f18, TASK_THREAD_F18_F0(a0)
-   fld f19, TASK_THREAD_F19_F0(a0)
-   fld f20, TASK_THREAD_F20_F0(a0)
-   fld f21, TASK_THREAD_F21_F0(a0)
-   fld f22, TASK_THREAD_F22_F0(a0)
-   fld f23, TASK_THREAD_F23_F0(a0)
-   fld f24, TASK_THREAD_F24_F0(a0)
-   fld f25, TASK_THREAD_F25_F0(a0)
-   fld f26, TASK_THREAD_F26_F0(a0)
-   fld f27, TASK_THREAD_F27_F0(a0)
-   fld f28, TASK_THREAD_F28_F0(a0)
-   fld f29, TASK_THREAD_F29_F0(a0)
-   fld f30, TASK_THREAD_F30_F0(a0)
-   fld f31, TASK_THREAD_F31_F0(a0)
-   fscsr t0
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_restore)
-
-
.section ".rodata"
/* Exception vector table */
 ENTRY(excp_vect_table)
diff --git a/arch/riscv/kernel/fpu.S b/arch/riscv/kernel/fpu.S
new file mode 100644
index ..1defb0618aff
--- /dev/null
+++ b/arch/riscv/kernel/fpu.S
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2012 Regents of the University of California
+ * Copyright (C) 2017 SiFive
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include 
+

[PATCH v5 0/5] riscv: Add support to no-FPU systems

2018-08-09 Thread Alan Kao
This patchset adds an option, CONFIG_FPU, to enable/disable floating-
point procedures.

Kernel's new behavior will be as follows:

* with CONFIG_FPU=y
  All FPU codes are reserved.  If no FPU is found during booting, a
  global flag will be set, and those functions will be bypassed with
  condition check to that flag.

* with CONFIG_FPU=n
  No floating-point instructions in kernel and all related settings
  are excluded.

Changes in v5:
 - Invert the polarity of checking flag from no_fpu to has_fpu.

Changes in v4:
 - Append a new patch to detect existence of FPU and followups.
 - Add SPDX header to newly created fpu.S.
 - Fix a build error, sorry for that.
 - Fix wording, style, etc.

Changes in v3:
 - Refactor the whole patch into independent ones.

Changes in v2:
 - Various code cleanups and style fixes.

Alan Kao (5):
  Extract FPU context operations from entry.S
  Refactor FPU code in signal setup/return procedures
  Cleanup ISA string setting
  Allow to disable FPU support
  Auto-detect whether a FPU exists

 arch/riscv/Kconfig |   9 +++
 arch/riscv/Makefile|  19 +++---
 arch/riscv/include/asm/hwcap.h |   1 +
 arch/riscv/include/asm/switch_to.h |  13 +++-
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/cpufeature.c |   8 +++
 arch/riscv/kernel/entry.S  |  87 ---
 arch/riscv/kernel/fpu.S| 106 +
 arch/riscv/kernel/process.c|   6 +-
 arch/riscv/kernel/signal.c |  75 
 10 files changed, 198 insertions(+), 127 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

-- 
2.18.0



[PATCH v4 4/5] Allow to disable FPU support

2018-08-07 Thread Alan Kao
FPU codes have been separated from common part in previous patches.
This patch add the CONFIG_FPU option and some stubs, so that a no-FPU
configuration is allowed.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/Kconfig |  9 +
 arch/riscv/include/asm/switch_to.h | 10 ++
 arch/riscv/kernel/Makefile |  2 +-
 arch/riscv/kernel/process.c|  4 +++-
 arch/riscv/kernel/signal.c |  5 +
 5 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 6debcc4afc72..6069597ba73f 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -232,6 +232,15 @@ config RISCV_BASE_PMU
 
 endmenu
 
+config FPU
+   bool "FPU support"
+   default y
+   help
+ Say N here if you want to disable all floating-point related procedure
+ in the kernel.
+
+ If you don't know what to do here, say Y.
+
 endmenu
 
 menu "Kernel type"
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index dd6b05bff75b..093050b03543 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -18,6 +18,7 @@
 #include 
 #include 
 
+#ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
 extern void __fstate_restore(struct task_struct *restore_from);
 
@@ -55,6 +56,15 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
+
+#else
+#define fstate_save(task, regs) do { } while (0)
+#define fstate_restore(task, regs) do { } while (0)
+#define __switch_to_aux(__prev, __next) do { } while (0)
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
+#endif
+
 extern struct task_struct *__switch_to(struct task_struct *,
   struct task_struct *);
 
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index bd433efd915e..f13f7f276639 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,7 +13,6 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
-obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
@@ -32,6 +31,7 @@ obj-y += vdso/
 
 CFLAGS_setup.o := -mcmodel=medany
 
+obj-$(CONFIG_FPU)  += fpu.o
 obj-$(CONFIG_SMP)  += smpboot.o
 obj-$(CONFIG_SMP)  += smp.o
 obj-$(CONFIG_MODULES)  += module.o
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index cb209139ba53..3820d89e2db9 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -83,7 +83,7 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
+   regs->sstatus = DEFAULT_SSTATUS;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
@@ -91,12 +91,14 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
 
 void flush_thread(void)
 {
+#ifdef CONFIG_FPU
/*
 * Reset FPU context
 *  frm: round to nearest, ties to even (IEEE default)
 *  fflags: accrued exceptions cleared
 */
memset(>thread.fstate, 0, sizeof(current->thread.fstate));
+#endif
 }
 
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 6a18b9819ead..2450b824d799 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,6 +37,7 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
+#ifdef CONFIG_FPU
 static long restore_fp_state(struct pt_regs *regs,
 union __riscv_fp_state *sc_fpregs)
 {
@@ -85,6 +86,10 @@ static long save_fp_state(struct pt_regs *regs,
 
return err;
 }
+#else
+#define save_fp_state(task, regs) (0)
+#define restore_fp_state(task, regs) (0)
+#endif
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
-- 
2.18.0



[PATCH v4 4/5] Allow to disable FPU support

2018-08-07 Thread Alan Kao
FPU codes have been separated from common part in previous patches.
This patch add the CONFIG_FPU option and some stubs, so that a no-FPU
configuration is allowed.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/Kconfig |  9 +
 arch/riscv/include/asm/switch_to.h | 10 ++
 arch/riscv/kernel/Makefile |  2 +-
 arch/riscv/kernel/process.c|  4 +++-
 arch/riscv/kernel/signal.c |  5 +
 5 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 6debcc4afc72..6069597ba73f 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -232,6 +232,15 @@ config RISCV_BASE_PMU
 
 endmenu
 
+config FPU
+   bool "FPU support"
+   default y
+   help
+ Say N here if you want to disable all floating-point related procedure
+ in the kernel.
+
+ If you don't know what to do here, say Y.
+
 endmenu
 
 menu "Kernel type"
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index dd6b05bff75b..093050b03543 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -18,6 +18,7 @@
 #include 
 #include 
 
+#ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
 extern void __fstate_restore(struct task_struct *restore_from);
 
@@ -55,6 +56,15 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
+
+#else
+#define fstate_save(task, regs) do { } while (0)
+#define fstate_restore(task, regs) do { } while (0)
+#define __switch_to_aux(__prev, __next) do { } while (0)
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
+#endif
+
 extern struct task_struct *__switch_to(struct task_struct *,
   struct task_struct *);
 
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index bd433efd915e..f13f7f276639 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,7 +13,6 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
-obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
@@ -32,6 +31,7 @@ obj-y += vdso/
 
 CFLAGS_setup.o := -mcmodel=medany
 
+obj-$(CONFIG_FPU)  += fpu.o
 obj-$(CONFIG_SMP)  += smpboot.o
 obj-$(CONFIG_SMP)  += smp.o
 obj-$(CONFIG_MODULES)  += module.o
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index cb209139ba53..3820d89e2db9 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -83,7 +83,7 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
+   regs->sstatus = DEFAULT_SSTATUS;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
@@ -91,12 +91,14 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
 
 void flush_thread(void)
 {
+#ifdef CONFIG_FPU
/*
 * Reset FPU context
 *  frm: round to nearest, ties to even (IEEE default)
 *  fflags: accrued exceptions cleared
 */
memset(>thread.fstate, 0, sizeof(current->thread.fstate));
+#endif
 }
 
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 6a18b9819ead..2450b824d799 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,6 +37,7 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
+#ifdef CONFIG_FPU
 static long restore_fp_state(struct pt_regs *regs,
 union __riscv_fp_state *sc_fpregs)
 {
@@ -85,6 +86,10 @@ static long save_fp_state(struct pt_regs *regs,
 
return err;
 }
+#else
+#define save_fp_state(task, regs) (0)
+#define restore_fp_state(task, regs) (0)
+#endif
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
-- 
2.18.0



[PATCH v4 1/5] Extract FPU context operations from entry.S

2018-08-07 Thread Alan Kao
We move __fstate_save and __fstate_restore to a new source
file, fpu.S.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/entry.S  |  87 --
 arch/riscv/kernel/fpu.S| 106 +
 3 files changed, 107 insertions(+), 87 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index e1274fc03af4..bd433efd915e 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,6 +13,7 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
+obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index 9aaf6c986771..edcd5920ee4e 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -357,93 +357,6 @@ ENTRY(__switch_to)
ret
 ENDPROC(__switch_to)
 
-ENTRY(__fstate_save)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   csrs sstatus, t1
-   frcsr t0
-   fsd f0,  TASK_THREAD_F0_F0(a0)
-   fsd f1,  TASK_THREAD_F1_F0(a0)
-   fsd f2,  TASK_THREAD_F2_F0(a0)
-   fsd f3,  TASK_THREAD_F3_F0(a0)
-   fsd f4,  TASK_THREAD_F4_F0(a0)
-   fsd f5,  TASK_THREAD_F5_F0(a0)
-   fsd f6,  TASK_THREAD_F6_F0(a0)
-   fsd f7,  TASK_THREAD_F7_F0(a0)
-   fsd f8,  TASK_THREAD_F8_F0(a0)
-   fsd f9,  TASK_THREAD_F9_F0(a0)
-   fsd f10, TASK_THREAD_F10_F0(a0)
-   fsd f11, TASK_THREAD_F11_F0(a0)
-   fsd f12, TASK_THREAD_F12_F0(a0)
-   fsd f13, TASK_THREAD_F13_F0(a0)
-   fsd f14, TASK_THREAD_F14_F0(a0)
-   fsd f15, TASK_THREAD_F15_F0(a0)
-   fsd f16, TASK_THREAD_F16_F0(a0)
-   fsd f17, TASK_THREAD_F17_F0(a0)
-   fsd f18, TASK_THREAD_F18_F0(a0)
-   fsd f19, TASK_THREAD_F19_F0(a0)
-   fsd f20, TASK_THREAD_F20_F0(a0)
-   fsd f21, TASK_THREAD_F21_F0(a0)
-   fsd f22, TASK_THREAD_F22_F0(a0)
-   fsd f23, TASK_THREAD_F23_F0(a0)
-   fsd f24, TASK_THREAD_F24_F0(a0)
-   fsd f25, TASK_THREAD_F25_F0(a0)
-   fsd f26, TASK_THREAD_F26_F0(a0)
-   fsd f27, TASK_THREAD_F27_F0(a0)
-   fsd f28, TASK_THREAD_F28_F0(a0)
-   fsd f29, TASK_THREAD_F29_F0(a0)
-   fsd f30, TASK_THREAD_F30_F0(a0)
-   fsd f31, TASK_THREAD_F31_F0(a0)
-   sw t0, TASK_THREAD_FCSR_F0(a0)
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_save)
-
-ENTRY(__fstate_restore)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   lw t0, TASK_THREAD_FCSR_F0(a0)
-   csrs sstatus, t1
-   fld f0,  TASK_THREAD_F0_F0(a0)
-   fld f1,  TASK_THREAD_F1_F0(a0)
-   fld f2,  TASK_THREAD_F2_F0(a0)
-   fld f3,  TASK_THREAD_F3_F0(a0)
-   fld f4,  TASK_THREAD_F4_F0(a0)
-   fld f5,  TASK_THREAD_F5_F0(a0)
-   fld f6,  TASK_THREAD_F6_F0(a0)
-   fld f7,  TASK_THREAD_F7_F0(a0)
-   fld f8,  TASK_THREAD_F8_F0(a0)
-   fld f9,  TASK_THREAD_F9_F0(a0)
-   fld f10, TASK_THREAD_F10_F0(a0)
-   fld f11, TASK_THREAD_F11_F0(a0)
-   fld f12, TASK_THREAD_F12_F0(a0)
-   fld f13, TASK_THREAD_F13_F0(a0)
-   fld f14, TASK_THREAD_F14_F0(a0)
-   fld f15, TASK_THREAD_F15_F0(a0)
-   fld f16, TASK_THREAD_F16_F0(a0)
-   fld f17, TASK_THREAD_F17_F0(a0)
-   fld f18, TASK_THREAD_F18_F0(a0)
-   fld f19, TASK_THREAD_F19_F0(a0)
-   fld f20, TASK_THREAD_F20_F0(a0)
-   fld f21, TASK_THREAD_F21_F0(a0)
-   fld f22, TASK_THREAD_F22_F0(a0)
-   fld f23, TASK_THREAD_F23_F0(a0)
-   fld f24, TASK_THREAD_F24_F0(a0)
-   fld f25, TASK_THREAD_F25_F0(a0)
-   fld f26, TASK_THREAD_F26_F0(a0)
-   fld f27, TASK_THREAD_F27_F0(a0)
-   fld f28, TASK_THREAD_F28_F0(a0)
-   fld f29, TASK_THREAD_F29_F0(a0)
-   fld f30, TASK_THREAD_F30_F0(a0)
-   fld f31, TASK_THREAD_F31_F0(a0)
-   fscsr t0
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_restore)
-
-
.section ".rodata"
/* Exception vector table */
 ENTRY(excp_vect_table)
diff --git a/arch/riscv/kernel/fpu.S b/arch/riscv/kernel/fpu.S
new file mode 100644
index ..1defb0618aff
--- /dev/null
+++ b/arch/riscv/kernel/fpu.S
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2012 Regents of the University of California
+ * Copyright (C) 2017 SiFive
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include 
+

[PATCH v4 1/5] Extract FPU context operations from entry.S

2018-08-07 Thread Alan Kao
We move __fstate_save and __fstate_restore to a new source
file, fpu.S.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/entry.S  |  87 --
 arch/riscv/kernel/fpu.S| 106 +
 3 files changed, 107 insertions(+), 87 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index e1274fc03af4..bd433efd915e 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,6 +13,7 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
+obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index 9aaf6c986771..edcd5920ee4e 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -357,93 +357,6 @@ ENTRY(__switch_to)
ret
 ENDPROC(__switch_to)
 
-ENTRY(__fstate_save)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   csrs sstatus, t1
-   frcsr t0
-   fsd f0,  TASK_THREAD_F0_F0(a0)
-   fsd f1,  TASK_THREAD_F1_F0(a0)
-   fsd f2,  TASK_THREAD_F2_F0(a0)
-   fsd f3,  TASK_THREAD_F3_F0(a0)
-   fsd f4,  TASK_THREAD_F4_F0(a0)
-   fsd f5,  TASK_THREAD_F5_F0(a0)
-   fsd f6,  TASK_THREAD_F6_F0(a0)
-   fsd f7,  TASK_THREAD_F7_F0(a0)
-   fsd f8,  TASK_THREAD_F8_F0(a0)
-   fsd f9,  TASK_THREAD_F9_F0(a0)
-   fsd f10, TASK_THREAD_F10_F0(a0)
-   fsd f11, TASK_THREAD_F11_F0(a0)
-   fsd f12, TASK_THREAD_F12_F0(a0)
-   fsd f13, TASK_THREAD_F13_F0(a0)
-   fsd f14, TASK_THREAD_F14_F0(a0)
-   fsd f15, TASK_THREAD_F15_F0(a0)
-   fsd f16, TASK_THREAD_F16_F0(a0)
-   fsd f17, TASK_THREAD_F17_F0(a0)
-   fsd f18, TASK_THREAD_F18_F0(a0)
-   fsd f19, TASK_THREAD_F19_F0(a0)
-   fsd f20, TASK_THREAD_F20_F0(a0)
-   fsd f21, TASK_THREAD_F21_F0(a0)
-   fsd f22, TASK_THREAD_F22_F0(a0)
-   fsd f23, TASK_THREAD_F23_F0(a0)
-   fsd f24, TASK_THREAD_F24_F0(a0)
-   fsd f25, TASK_THREAD_F25_F0(a0)
-   fsd f26, TASK_THREAD_F26_F0(a0)
-   fsd f27, TASK_THREAD_F27_F0(a0)
-   fsd f28, TASK_THREAD_F28_F0(a0)
-   fsd f29, TASK_THREAD_F29_F0(a0)
-   fsd f30, TASK_THREAD_F30_F0(a0)
-   fsd f31, TASK_THREAD_F31_F0(a0)
-   sw t0, TASK_THREAD_FCSR_F0(a0)
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_save)
-
-ENTRY(__fstate_restore)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   lw t0, TASK_THREAD_FCSR_F0(a0)
-   csrs sstatus, t1
-   fld f0,  TASK_THREAD_F0_F0(a0)
-   fld f1,  TASK_THREAD_F1_F0(a0)
-   fld f2,  TASK_THREAD_F2_F0(a0)
-   fld f3,  TASK_THREAD_F3_F0(a0)
-   fld f4,  TASK_THREAD_F4_F0(a0)
-   fld f5,  TASK_THREAD_F5_F0(a0)
-   fld f6,  TASK_THREAD_F6_F0(a0)
-   fld f7,  TASK_THREAD_F7_F0(a0)
-   fld f8,  TASK_THREAD_F8_F0(a0)
-   fld f9,  TASK_THREAD_F9_F0(a0)
-   fld f10, TASK_THREAD_F10_F0(a0)
-   fld f11, TASK_THREAD_F11_F0(a0)
-   fld f12, TASK_THREAD_F12_F0(a0)
-   fld f13, TASK_THREAD_F13_F0(a0)
-   fld f14, TASK_THREAD_F14_F0(a0)
-   fld f15, TASK_THREAD_F15_F0(a0)
-   fld f16, TASK_THREAD_F16_F0(a0)
-   fld f17, TASK_THREAD_F17_F0(a0)
-   fld f18, TASK_THREAD_F18_F0(a0)
-   fld f19, TASK_THREAD_F19_F0(a0)
-   fld f20, TASK_THREAD_F20_F0(a0)
-   fld f21, TASK_THREAD_F21_F0(a0)
-   fld f22, TASK_THREAD_F22_F0(a0)
-   fld f23, TASK_THREAD_F23_F0(a0)
-   fld f24, TASK_THREAD_F24_F0(a0)
-   fld f25, TASK_THREAD_F25_F0(a0)
-   fld f26, TASK_THREAD_F26_F0(a0)
-   fld f27, TASK_THREAD_F27_F0(a0)
-   fld f28, TASK_THREAD_F28_F0(a0)
-   fld f29, TASK_THREAD_F29_F0(a0)
-   fld f30, TASK_THREAD_F30_F0(a0)
-   fld f31, TASK_THREAD_F31_F0(a0)
-   fscsr t0
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_restore)
-
-
.section ".rodata"
/* Exception vector table */
 ENTRY(excp_vect_table)
diff --git a/arch/riscv/kernel/fpu.S b/arch/riscv/kernel/fpu.S
new file mode 100644
index ..1defb0618aff
--- /dev/null
+++ b/arch/riscv/kernel/fpu.S
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2012 Regents of the University of California
+ * Copyright (C) 2017 SiFive
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include 
+

[PATCH v4 5/5] Auto-detect whether a FPU exists

2018-08-07 Thread Alan Kao
We expect that a kernel with CONFIG_FPU=y can still support no-FPU machines.
To do so, the kernel should first examine the existence of a FPU, then
do nothing if a FPU does exist; otherwise, it should disable/bypass all
FPU-related functions.

In this patch, a new global variable, no_fpu, is created and determined
when parsing the hardware capability from device tree during booting.
This variable is used in those FPU-related functions.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/include/asm/hwcap.h |  3 +++
 arch/riscv/include/asm/switch_to.h | 13 -
 arch/riscv/kernel/cpufeature.c | 11 +++
 arch/riscv/kernel/signal.c |  6 ++
 4 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
index 8a4ed7bbcbea..1b870086a869 100644
--- a/arch/riscv/include/asm/hwcap.h
+++ b/arch/riscv/include/asm/hwcap.h
@@ -33,5 +33,8 @@ enum {
 };
 
 extern unsigned long elf_hwcap;
+#ifdef CONFIG_FPU
+extern bool no_fpu;
+#endif
 #endif
 #endif
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index 093050b03543..7278e3eb7a70 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
@@ -30,6 +31,9 @@ static inline void __fstate_clean(struct pt_regs *regs)
 static inline void fstate_save(struct task_struct *task,
   struct pt_regs *regs)
 {
+   if (unlikely(no_fpu))
+   return;
+
if ((regs->sstatus & SR_FS) == SR_FS_DIRTY) {
__fstate_save(task);
__fstate_clean(regs);
@@ -39,6 +43,9 @@ static inline void fstate_save(struct task_struct *task,
 static inline void fstate_restore(struct task_struct *task,
  struct pt_regs *regs)
 {
+   if (unlikely(no_fpu))
+   return;
+
if ((regs->sstatus & SR_FS) != SR_FS_OFF) {
__fstate_restore(task);
__fstate_clean(regs);
@@ -50,13 +57,17 @@ static inline void __switch_to_aux(struct task_struct *prev,
 {
struct pt_regs *regs;
 
+   if (unlikely(no_fpu))
+   return;
+
regs = task_pt_regs(prev);
if (unlikely(regs->sstatus & SR_SD))
fstate_save(prev, regs);
fstate_restore(next, task_pt_regs(next));
 }
 
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
+#define DEFAULT_SSTATUS \
+   ((unlikely(no_fpu)) ? (SR_SPIE | SR_FS_OFF) : (SR_SPIE | SR_FS_INITIAL))
 
 #else
 #define fstate_save(task, regs) do { } while (0)
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 17011a870044..bc269c1e0b1a 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -22,6 +22,9 @@
 #include 
 
 unsigned long elf_hwcap __read_mostly;
+#ifdef CONFIG_FPU
+bool no_fpu __read_mostly;
+#endif
 
 void riscv_fill_hwcap(void)
 {
@@ -58,4 +61,12 @@ void riscv_fill_hwcap(void)
elf_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
 
pr_info("elf_hwcap is 0x%lx", elf_hwcap);
+
+#ifdef CONFIG_FPU
+   no_fpu = 0;
+   if (!(elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))) {
+   pr_info("Bypass FPU code.");
+   no_fpu = 1;
+   }
+#endif
 }
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 2450b824d799..9714e4fccb69 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -45,6 +45,9 @@ static long restore_fp_state(struct pt_regs *regs,
struct __riscv_d_ext_state __user *state = _fpregs->d;
size_t i;
 
+   if (unlikely(no_fpu))
+   return 0;
+
err = __copy_from_user(>thread.fstate, state, sizeof(*state));
if (unlikely(err))
return err;
@@ -72,6 +75,9 @@ static long save_fp_state(struct pt_regs *regs,
struct __riscv_d_ext_state __user *state = _fpregs->d;
size_t i;
 
+   if (unlikely(no_fpu))
+   return 0;
+
fstate_save(current, regs);
err = __copy_to_user(state, >thread.fstate, sizeof(*state));
if (unlikely(err))
-- 
2.18.0



[PATCH v4 2/5] Refactor FPU code in signal setup/return procedures

2018-08-07 Thread Alan Kao
FPU-related logic is separated from normal signal handling path in
this patch.  Kernel can easily be configured to exclude those procedures
for no-FPU systems.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/kernel/signal.c | 68 +++---
 1 file changed, 41 insertions(+), 27 deletions(-)

diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 718d0c984ef0..6a18b9819ead 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,45 +37,63 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
-static long restore_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long restore_fp_state(struct pt_regs *regs,
+union __riscv_fp_state *sc_fpregs)
 {
long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
err = __copy_from_user(>thread.fstate, state, sizeof(*state));
-   if (likely(!err))
-   fstate_restore(current, regs);
+   if (unlikely(err))
+   return err;
+
+   fstate_restore(current, regs);
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   u32 value;
+
+   err = __get_user(value, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   if (value != 0)
+   return -EINVAL;
+   }
+
return err;
 }
 
-static long save_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long save_fp_state(struct pt_regs *regs,
+ union __riscv_fp_state *sc_fpregs)
 {
+   long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
fstate_save(current, regs);
-   return __copy_to_user(state, >thread.fstate, sizeof(*state));
+   err = __copy_to_user(state, >thread.fstate, sizeof(*state));
+   if (unlikely(err))
+   return err;
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   err = __put_user(0, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   }
+
+   return err;
 }
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
 {
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
-   if (unlikely(err))
-   return err;
/* Restore the floating-point state. */
-   err = restore_d_state(regs, >sc_fpregs.d);
-   if (unlikely(err))
-   return err;
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) {
-   u32 value;
-   err = __get_user(value, >sc_fpregs.q.reserved[i]);
-   if (unlikely(err))
-   break;
-   if (value != 0)
-   return -EINVAL;
-   }
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -124,14 +142,10 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
 {
struct sigcontext __user *sc = >uc.uc_mcontext;
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_d_state(regs, >sc_fpregs.d);
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++)
-   err |= __put_user(0, >sc_fpregs.q.reserved[i]);
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.18.0



[PATCH v4 3/5] Cleanup ISA string setting

2018-08-07 Thread Alan Kao
Just a side note: (Assume that atomic and compressed is on)

Before this patch, assembler was always given the riscv64imafdc
MARCH string because there are fld/fsd's in entry.S; compiler was
always given riscv64imac because kernel doesn't need floating point
code generation.  After this, the MARCH string in AFLAGS and CFLAGS
become the same.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/Makefile | 19 ---
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 6d4a5f6c3f4f..e0fe6790624f 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -26,7 +26,6 @@ ifeq ($(CONFIG_ARCH_RV64I),y)
 
KBUILD_CFLAGS += -mabi=lp64
KBUILD_AFLAGS += -mabi=lp64
-   KBUILD_MARCH = rv64im
LDFLAGS += -melf64lriscv
 else
BITS := 32
@@ -34,22 +33,20 @@ else
 
KBUILD_CFLAGS += -mabi=ilp32
KBUILD_AFLAGS += -mabi=ilp32
-   KBUILD_MARCH = rv32im
LDFLAGS += -melf32lriscv
 endif
 
 KBUILD_CFLAGS += -Wall
 
-ifeq ($(CONFIG_RISCV_ISA_A),y)
-   KBUILD_ARCH_A = a
-endif
-ifeq ($(CONFIG_RISCV_ISA_C),y)
-   KBUILD_ARCH_C = c
-endif
-
-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+# ISA string setting
+riscv-march-$(CONFIG_ARCH_RV32I)   := rv32im
+riscv-march-$(CONFIG_ARCH_RV64I)   := rv64im
+riscv-march-$(CONFIG_RISCV_ISA_A)  := $(riscv-march-y)a
+riscv-march-y  := $(riscv-march-y)fd
+riscv-march-$(CONFIG_RISCV_ISA_C)  := $(riscv-march-y)c
+KBUILD_CFLAGS += -march=$(riscv-march-y)
+KBUILD_AFLAGS += -march=$(riscv-march-y)
 
-KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
 KBUILD_CFLAGS += -mno-save-restore
 KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
 
-- 
2.18.0



[PATCH v4 5/5] Auto-detect whether a FPU exists

2018-08-07 Thread Alan Kao
We expect that a kernel with CONFIG_FPU=y can still support no-FPU machines.
To do so, the kernel should first examine the existence of a FPU, then
do nothing if a FPU does exist; otherwise, it should disable/bypass all
FPU-related functions.

In this patch, a new global variable, no_fpu, is created and determined
when parsing the hardware capability from device tree during booting.
This variable is used in those FPU-related functions.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/include/asm/hwcap.h |  3 +++
 arch/riscv/include/asm/switch_to.h | 13 -
 arch/riscv/kernel/cpufeature.c | 11 +++
 arch/riscv/kernel/signal.c |  6 ++
 4 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
index 8a4ed7bbcbea..1b870086a869 100644
--- a/arch/riscv/include/asm/hwcap.h
+++ b/arch/riscv/include/asm/hwcap.h
@@ -33,5 +33,8 @@ enum {
 };
 
 extern unsigned long elf_hwcap;
+#ifdef CONFIG_FPU
+extern bool no_fpu;
+#endif
 #endif
 #endif
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index 093050b03543..7278e3eb7a70 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
@@ -30,6 +31,9 @@ static inline void __fstate_clean(struct pt_regs *regs)
 static inline void fstate_save(struct task_struct *task,
   struct pt_regs *regs)
 {
+   if (unlikely(no_fpu))
+   return;
+
if ((regs->sstatus & SR_FS) == SR_FS_DIRTY) {
__fstate_save(task);
__fstate_clean(regs);
@@ -39,6 +43,9 @@ static inline void fstate_save(struct task_struct *task,
 static inline void fstate_restore(struct task_struct *task,
  struct pt_regs *regs)
 {
+   if (unlikely(no_fpu))
+   return;
+
if ((regs->sstatus & SR_FS) != SR_FS_OFF) {
__fstate_restore(task);
__fstate_clean(regs);
@@ -50,13 +57,17 @@ static inline void __switch_to_aux(struct task_struct *prev,
 {
struct pt_regs *regs;
 
+   if (unlikely(no_fpu))
+   return;
+
regs = task_pt_regs(prev);
if (unlikely(regs->sstatus & SR_SD))
fstate_save(prev, regs);
fstate_restore(next, task_pt_regs(next));
 }
 
-#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
+#define DEFAULT_SSTATUS \
+   ((unlikely(no_fpu)) ? (SR_SPIE | SR_FS_OFF) : (SR_SPIE | SR_FS_INITIAL))
 
 #else
 #define fstate_save(task, regs) do { } while (0)
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 17011a870044..bc269c1e0b1a 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -22,6 +22,9 @@
 #include 
 
 unsigned long elf_hwcap __read_mostly;
+#ifdef CONFIG_FPU
+bool no_fpu __read_mostly;
+#endif
 
 void riscv_fill_hwcap(void)
 {
@@ -58,4 +61,12 @@ void riscv_fill_hwcap(void)
elf_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
 
pr_info("elf_hwcap is 0x%lx", elf_hwcap);
+
+#ifdef CONFIG_FPU
+   no_fpu = 0;
+   if (!(elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))) {
+   pr_info("Bypass FPU code.");
+   no_fpu = 1;
+   }
+#endif
 }
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 2450b824d799..9714e4fccb69 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -45,6 +45,9 @@ static long restore_fp_state(struct pt_regs *regs,
struct __riscv_d_ext_state __user *state = _fpregs->d;
size_t i;
 
+   if (unlikely(no_fpu))
+   return 0;
+
err = __copy_from_user(>thread.fstate, state, sizeof(*state));
if (unlikely(err))
return err;
@@ -72,6 +75,9 @@ static long save_fp_state(struct pt_regs *regs,
struct __riscv_d_ext_state __user *state = _fpregs->d;
size_t i;
 
+   if (unlikely(no_fpu))
+   return 0;
+
fstate_save(current, regs);
err = __copy_to_user(state, >thread.fstate, sizeof(*state));
if (unlikely(err))
-- 
2.18.0



[PATCH v4 2/5] Refactor FPU code in signal setup/return procedures

2018-08-07 Thread Alan Kao
FPU-related logic is separated from normal signal handling path in
this patch.  Kernel can easily be configured to exclude those procedures
for no-FPU systems.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/kernel/signal.c | 68 +++---
 1 file changed, 41 insertions(+), 27 deletions(-)

diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 718d0c984ef0..6a18b9819ead 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,45 +37,63 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
-static long restore_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long restore_fp_state(struct pt_regs *regs,
+union __riscv_fp_state *sc_fpregs)
 {
long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
err = __copy_from_user(>thread.fstate, state, sizeof(*state));
-   if (likely(!err))
-   fstate_restore(current, regs);
+   if (unlikely(err))
+   return err;
+
+   fstate_restore(current, regs);
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   u32 value;
+
+   err = __get_user(value, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   if (value != 0)
+   return -EINVAL;
+   }
+
return err;
 }
 
-static long save_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long save_fp_state(struct pt_regs *regs,
+ union __riscv_fp_state *sc_fpregs)
 {
+   long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
fstate_save(current, regs);
-   return __copy_to_user(state, >thread.fstate, sizeof(*state));
+   err = __copy_to_user(state, >thread.fstate, sizeof(*state));
+   if (unlikely(err))
+   return err;
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   err = __put_user(0, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   }
+
+   return err;
 }
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
 {
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
-   if (unlikely(err))
-   return err;
/* Restore the floating-point state. */
-   err = restore_d_state(regs, >sc_fpregs.d);
-   if (unlikely(err))
-   return err;
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) {
-   u32 value;
-   err = __get_user(value, >sc_fpregs.q.reserved[i]);
-   if (unlikely(err))
-   break;
-   if (value != 0)
-   return -EINVAL;
-   }
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -124,14 +142,10 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
 {
struct sigcontext __user *sc = >uc.uc_mcontext;
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_d_state(regs, >sc_fpregs.d);
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++)
-   err |= __put_user(0, >sc_fpregs.q.reserved[i]);
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.18.0



[PATCH v4 3/5] Cleanup ISA string setting

2018-08-07 Thread Alan Kao
Just a side note: (Assume that atomic and compressed is on)

Before this patch, assembler was always given the riscv64imafdc
MARCH string because there are fld/fsd's in entry.S; compiler was
always given riscv64imac because kernel doesn't need floating point
code generation.  After this, the MARCH string in AFLAGS and CFLAGS
become the same.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
Reviewed-by: Christoph Hellwig 
---
 arch/riscv/Makefile | 19 ---
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 6d4a5f6c3f4f..e0fe6790624f 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -26,7 +26,6 @@ ifeq ($(CONFIG_ARCH_RV64I),y)
 
KBUILD_CFLAGS += -mabi=lp64
KBUILD_AFLAGS += -mabi=lp64
-   KBUILD_MARCH = rv64im
LDFLAGS += -melf64lriscv
 else
BITS := 32
@@ -34,22 +33,20 @@ else
 
KBUILD_CFLAGS += -mabi=ilp32
KBUILD_AFLAGS += -mabi=ilp32
-   KBUILD_MARCH = rv32im
LDFLAGS += -melf32lriscv
 endif
 
 KBUILD_CFLAGS += -Wall
 
-ifeq ($(CONFIG_RISCV_ISA_A),y)
-   KBUILD_ARCH_A = a
-endif
-ifeq ($(CONFIG_RISCV_ISA_C),y)
-   KBUILD_ARCH_C = c
-endif
-
-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+# ISA string setting
+riscv-march-$(CONFIG_ARCH_RV32I)   := rv32im
+riscv-march-$(CONFIG_ARCH_RV64I)   := rv64im
+riscv-march-$(CONFIG_RISCV_ISA_A)  := $(riscv-march-y)a
+riscv-march-y  := $(riscv-march-y)fd
+riscv-march-$(CONFIG_RISCV_ISA_C)  := $(riscv-march-y)c
+KBUILD_CFLAGS += -march=$(riscv-march-y)
+KBUILD_AFLAGS += -march=$(riscv-march-y)
 
-KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
 KBUILD_CFLAGS += -mno-save-restore
 KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
 
-- 
2.18.0



[PATCH v4 0/5] riscv: Add support to no-FPU systems

2018-08-07 Thread Alan Kao
This patchset adds an option, CONFIG_FPU, to enable/disable floating-
point procedures.

Kernel's new behavior will be as follows:

* with CONFIG_FPU=y
  All FPU codes are reserved.  If no FPU is found during booting, a
  global flag will be set, and those functions will be bypassed with
  condition check to that flag.

* with CONFIG_FPU=n
  No floating-point instructions in kernel and all related settings
  are excluded.

Changes in v4:
 - Append a new patch to detect existence of FPU and followups.
 - Add SPDX header to newly created fpu.S.
 - Fix a build error, sorry for that.
 - Fix wording, style, etc.

Changes in v3:
 - Refactor the whole patch into independent ones.

Changes in v2:
 - Various code cleanups and style fixes.

Alan Kao (5):
  Extract FPU context operations from entry.S
  Refactor FPU code in signal setup/return procedures
  Cleanup ISA string setting
  Allow to disable FPU support
  Auto-detect whether a FPU exists

 arch/riscv/Kconfig |   9 +++
 arch/riscv/Makefile|  19 +++---
 arch/riscv/include/asm/hwcap.h |   3 +
 arch/riscv/include/asm/switch_to.h |  21 ++
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/cpufeature.c |  11 +++
 arch/riscv/kernel/entry.S  |  87 ---
 arch/riscv/kernel/fpu.S| 106 +
 arch/riscv/kernel/process.c|   4 +-
 arch/riscv/kernel/signal.c |  79 +
 10 files changed, 214 insertions(+), 126 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

-- 
2.18.0



[PATCH v4 0/5] riscv: Add support to no-FPU systems

2018-08-07 Thread Alan Kao
This patchset adds an option, CONFIG_FPU, to enable/disable floating-
point procedures.

Kernel's new behavior will be as follows:

* with CONFIG_FPU=y
  All FPU codes are reserved.  If no FPU is found during booting, a
  global flag will be set, and those functions will be bypassed with
  condition check to that flag.

* with CONFIG_FPU=n
  No floating-point instructions in kernel and all related settings
  are excluded.

Changes in v4:
 - Append a new patch to detect existence of FPU and followups.
 - Add SPDX header to newly created fpu.S.
 - Fix a build error, sorry for that.
 - Fix wording, style, etc.

Changes in v3:
 - Refactor the whole patch into independent ones.

Changes in v2:
 - Various code cleanups and style fixes.

Alan Kao (5):
  Extract FPU context operations from entry.S
  Refactor FPU code in signal setup/return procedures
  Cleanup ISA string setting
  Allow to disable FPU support
  Auto-detect whether a FPU exists

 arch/riscv/Kconfig |   9 +++
 arch/riscv/Makefile|  19 +++---
 arch/riscv/include/asm/hwcap.h |   3 +
 arch/riscv/include/asm/switch_to.h |  21 ++
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/cpufeature.c |  11 +++
 arch/riscv/kernel/entry.S  |  87 ---
 arch/riscv/kernel/fpu.S| 106 +
 arch/riscv/kernel/process.c|   4 +-
 arch/riscv/kernel/signal.c |  79 +
 10 files changed, 214 insertions(+), 126 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

-- 
2.18.0



Re: [PATCH v2] riscv: Add support to no-FPU systems

2018-08-05 Thread Alan Kao
On Fri, Aug 03, 2018 at 09:03:00PM -0700, Palmer Dabbelt wrote:
> On Wed, 01 Aug 2018 11:23:43 PDT (-0700), Andrew Waterman wrote:
> >On Wed, Aug 1, 2018 at 10:55 AM, Palmer Dabbelt  wrote:
> >>On Tue, 26 Jun 2018 21:22:26 PDT (-0700), alan...@andestech.com wrote:
> >>>
> >>>This patch adds an option, CONFIG_FPU, to enable/disable floating
> >>>procedures.  Also, some style issues are fixed.
> >>>
> >>>Signed-off-by: Alan Kao 
> >>>Cc: Greentime Hu 
> >>>Cc: Zong Li 
> >>>---
> >>> arch/riscv/Kconfig |  9 
> >>> arch/riscv/Makefile| 19 +++
> >>> arch/riscv/include/asm/switch_to.h |  6 +++
> >>> arch/riscv/kernel/entry.S  |  3 +-
> >>> arch/riscv/kernel/process.c|  7 ++-
> >>> arch/riscv/kernel/signal.c | 82 +-
> >>> 6 files changed, 90 insertions(+), 36 deletions(-)
> >>>
> >>>diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> >>>index 6debcc4afc72..6069597ba73f 100644
> >>>--- a/arch/riscv/Kconfig
> >>>+++ b/arch/riscv/Kconfig
> >>>@@ -232,6 +232,15 @@ config RISCV_BASE_PMU
> >>>
> >>> endmenu
> >>>
> >>>+config FPU
> >>>+   bool "FPU support"
> >>>+   default y
> >>>+   help
> >>>+ Say N here if you want to disable all floating-point related
> >>>procedure
> >>>+ in the kernel.
> >>>+
> >>>+ If you don't know what to do here, say Y.
> >>>+
> >>> endmenu
> >>
> >>
> >>Sorry for letting this slide for a bit.  While I'm not opposed to a solution
> >>that requires a FPU Kconfig option, it'd be a bit better if we could detect
> >>this at boot time.  I think this should be possible because at one point
> >>this actually worked and we could boot the same kernel on FPU and no-FPU
> >>systems.
> >
> >I believe it would suffice to have start_thread set sstatus.FS to OFF
> >for no-FPU systems (vs. INITIAL for systems with FPU).   The ISA
> >string in the devicetree should indicate whether F/D extensions are
> >present.
> >
> >That said, it makes sense to me to additionally provide the Kconfig
> >option.  This would elide the sstatus.SD check for no-FPU systems,
> >shaving a couple instructions off the context-switch path.  It would
> >also enable mimicking the behavior of a no-FPU system even when the
> >FPU is present.
> 
> That sounds like a good argument.  Do you mind submitting a two-part patch
> set, to:
> 
> * Allow FPU kernels to detect and run correctly on non-FPU systems.  You
> should  be able to detect these very early by writing to sstatus, or later
> by looking  at the device tree.
> * Add a Kconfig option to disable the FPU entirely (which is pretty much
> this  patch).
> 
> Thanks!
> 

Thanks for the feedback from all of you.

We will fix v3 according to Christph's suggestions,
and append a new patch of the auto-detecting feature.


Re: [PATCH v2] riscv: Add support to no-FPU systems

2018-08-05 Thread Alan Kao
On Fri, Aug 03, 2018 at 09:03:00PM -0700, Palmer Dabbelt wrote:
> On Wed, 01 Aug 2018 11:23:43 PDT (-0700), Andrew Waterman wrote:
> >On Wed, Aug 1, 2018 at 10:55 AM, Palmer Dabbelt  wrote:
> >>On Tue, 26 Jun 2018 21:22:26 PDT (-0700), alan...@andestech.com wrote:
> >>>
> >>>This patch adds an option, CONFIG_FPU, to enable/disable floating
> >>>procedures.  Also, some style issues are fixed.
> >>>
> >>>Signed-off-by: Alan Kao 
> >>>Cc: Greentime Hu 
> >>>Cc: Zong Li 
> >>>---
> >>> arch/riscv/Kconfig |  9 
> >>> arch/riscv/Makefile| 19 +++
> >>> arch/riscv/include/asm/switch_to.h |  6 +++
> >>> arch/riscv/kernel/entry.S  |  3 +-
> >>> arch/riscv/kernel/process.c|  7 ++-
> >>> arch/riscv/kernel/signal.c | 82 +-
> >>> 6 files changed, 90 insertions(+), 36 deletions(-)
> >>>
> >>>diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> >>>index 6debcc4afc72..6069597ba73f 100644
> >>>--- a/arch/riscv/Kconfig
> >>>+++ b/arch/riscv/Kconfig
> >>>@@ -232,6 +232,15 @@ config RISCV_BASE_PMU
> >>>
> >>> endmenu
> >>>
> >>>+config FPU
> >>>+   bool "FPU support"
> >>>+   default y
> >>>+   help
> >>>+ Say N here if you want to disable all floating-point related
> >>>procedure
> >>>+ in the kernel.
> >>>+
> >>>+ If you don't know what to do here, say Y.
> >>>+
> >>> endmenu
> >>
> >>
> >>Sorry for letting this slide for a bit.  While I'm not opposed to a solution
> >>that requires a FPU Kconfig option, it'd be a bit better if we could detect
> >>this at boot time.  I think this should be possible because at one point
> >>this actually worked and we could boot the same kernel on FPU and no-FPU
> >>systems.
> >
> >I believe it would suffice to have start_thread set sstatus.FS to OFF
> >for no-FPU systems (vs. INITIAL for systems with FPU).   The ISA
> >string in the devicetree should indicate whether F/D extensions are
> >present.
> >
> >That said, it makes sense to me to additionally provide the Kconfig
> >option.  This would elide the sstatus.SD check for no-FPU systems,
> >shaving a couple instructions off the context-switch path.  It would
> >also enable mimicking the behavior of a no-FPU system even when the
> >FPU is present.
> 
> That sounds like a good argument.  Do you mind submitting a two-part patch
> set, to:
> 
> * Allow FPU kernels to detect and run correctly on non-FPU systems.  You
> should  be able to detect these very early by writing to sstatus, or later
> by looking  at the device tree.
> * Add a Kconfig option to disable the FPU entirely (which is pretty much
> this  patch).
> 
> Thanks!
> 

Thanks for the feedback from all of you.

We will fix v3 according to Christph's suggestions,
and append a new patch of the auto-detecting feature.


[PATCH v3 4/4] Add an option to support no-FPU systems

2018-08-01 Thread Alan Kao
FP codes have been separated from common part in previous patches.
This patch add the CONFIG_FPU option and some stubs to support
no-FPU systems.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/Kconfig |  9 +
 arch/riscv/include/asm/switch_to.h | 12 
 arch/riscv/kernel/Makefile |  2 +-
 arch/riscv/kernel/process.c|  4 +++-
 arch/riscv/kernel/signal.c |  2 ++
 5 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 6debcc4afc72..6069597ba73f 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -232,6 +232,15 @@ config RISCV_BASE_PMU
 
 endmenu
 
+config FPU
+   bool "FPU support"
+   default y
+   help
+ Say N here if you want to disable all floating-point related procedure
+ in the kernel.
+
+ If you don't know what to do here, say Y.
+
 endmenu
 
 menu "Kernel type"
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index dd6b05bff75b..94a08d28ccf5 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -18,6 +18,7 @@
 #include 
 #include 
 
+#ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
 extern void __fstate_restore(struct task_struct *restore_from);
 
@@ -55,6 +56,17 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
+
+#else
+#define save_fp_state(task, regs) (0)
+#define restore_fp_state(task, regs) (0)
+#define fstate_save(task, regs) do { } while (0)
+#define fstate_restore(task, regs) do { } while (0)
+#define __switch_to_aux(__prev, __next) do { } while (0)
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
+#endif
+
 extern struct task_struct *__switch_to(struct task_struct *,
   struct task_struct *);
 
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index bd433efd915e..f13f7f276639 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,7 +13,6 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
-obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
@@ -32,6 +31,7 @@ obj-y += vdso/
 
 CFLAGS_setup.o := -mcmodel=medany
 
+obj-$(CONFIG_FPU)  += fpu.o
 obj-$(CONFIG_SMP)  += smpboot.o
 obj-$(CONFIG_SMP)  += smp.o
 obj-$(CONFIG_MODULES)  += module.o
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index cb209139ba53..3820d89e2db9 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -83,7 +83,7 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
+   regs->sstatus = DEFAULT_SSTATUS;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
@@ -91,12 +91,14 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
 
 void flush_thread(void)
 {
+#ifdef CONFIG_FPU
/*
 * Reset FPU context
 *  frm: round to nearest, ties to even (IEEE default)
 *  fflags: accrued exceptions cleared
 */
memset(>thread.fstate, 0, sizeof(current->thread.fstate));
+#endif
 }
 
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index bfce852d5ddc..b7bbb5c33594 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,6 +37,7 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
+#ifdef CONFIG_FPU
 static long restore_fp_state(struct pt_regs *regs,
union __riscv_fp_state *sc_fpregs)
 {
@@ -85,6 +86,7 @@ static long save_fp_state(struct pt_regs *regs,
 
return err;
 }
+#endif
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
-- 
2.18.0



[PATCH v3 1/4] Extract FPU context operations from entry.S

2018-08-01 Thread Alan Kao
We move __fstate_save and __fstate_restore to a new source
file, fpu.S.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/entry.S  |  87 --
 arch/riscv/kernel/fpu.S| 105 +
 3 files changed, 106 insertions(+), 87 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index e1274fc03af4..bd433efd915e 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,6 +13,7 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
+obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index 9aaf6c986771..edcd5920ee4e 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -357,93 +357,6 @@ ENTRY(__switch_to)
ret
 ENDPROC(__switch_to)
 
-ENTRY(__fstate_save)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   csrs sstatus, t1
-   frcsr t0
-   fsd f0,  TASK_THREAD_F0_F0(a0)
-   fsd f1,  TASK_THREAD_F1_F0(a0)
-   fsd f2,  TASK_THREAD_F2_F0(a0)
-   fsd f3,  TASK_THREAD_F3_F0(a0)
-   fsd f4,  TASK_THREAD_F4_F0(a0)
-   fsd f5,  TASK_THREAD_F5_F0(a0)
-   fsd f6,  TASK_THREAD_F6_F0(a0)
-   fsd f7,  TASK_THREAD_F7_F0(a0)
-   fsd f8,  TASK_THREAD_F8_F0(a0)
-   fsd f9,  TASK_THREAD_F9_F0(a0)
-   fsd f10, TASK_THREAD_F10_F0(a0)
-   fsd f11, TASK_THREAD_F11_F0(a0)
-   fsd f12, TASK_THREAD_F12_F0(a0)
-   fsd f13, TASK_THREAD_F13_F0(a0)
-   fsd f14, TASK_THREAD_F14_F0(a0)
-   fsd f15, TASK_THREAD_F15_F0(a0)
-   fsd f16, TASK_THREAD_F16_F0(a0)
-   fsd f17, TASK_THREAD_F17_F0(a0)
-   fsd f18, TASK_THREAD_F18_F0(a0)
-   fsd f19, TASK_THREAD_F19_F0(a0)
-   fsd f20, TASK_THREAD_F20_F0(a0)
-   fsd f21, TASK_THREAD_F21_F0(a0)
-   fsd f22, TASK_THREAD_F22_F0(a0)
-   fsd f23, TASK_THREAD_F23_F0(a0)
-   fsd f24, TASK_THREAD_F24_F0(a0)
-   fsd f25, TASK_THREAD_F25_F0(a0)
-   fsd f26, TASK_THREAD_F26_F0(a0)
-   fsd f27, TASK_THREAD_F27_F0(a0)
-   fsd f28, TASK_THREAD_F28_F0(a0)
-   fsd f29, TASK_THREAD_F29_F0(a0)
-   fsd f30, TASK_THREAD_F30_F0(a0)
-   fsd f31, TASK_THREAD_F31_F0(a0)
-   sw t0, TASK_THREAD_FCSR_F0(a0)
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_save)
-
-ENTRY(__fstate_restore)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   lw t0, TASK_THREAD_FCSR_F0(a0)
-   csrs sstatus, t1
-   fld f0,  TASK_THREAD_F0_F0(a0)
-   fld f1,  TASK_THREAD_F1_F0(a0)
-   fld f2,  TASK_THREAD_F2_F0(a0)
-   fld f3,  TASK_THREAD_F3_F0(a0)
-   fld f4,  TASK_THREAD_F4_F0(a0)
-   fld f5,  TASK_THREAD_F5_F0(a0)
-   fld f6,  TASK_THREAD_F6_F0(a0)
-   fld f7,  TASK_THREAD_F7_F0(a0)
-   fld f8,  TASK_THREAD_F8_F0(a0)
-   fld f9,  TASK_THREAD_F9_F0(a0)
-   fld f10, TASK_THREAD_F10_F0(a0)
-   fld f11, TASK_THREAD_F11_F0(a0)
-   fld f12, TASK_THREAD_F12_F0(a0)
-   fld f13, TASK_THREAD_F13_F0(a0)
-   fld f14, TASK_THREAD_F14_F0(a0)
-   fld f15, TASK_THREAD_F15_F0(a0)
-   fld f16, TASK_THREAD_F16_F0(a0)
-   fld f17, TASK_THREAD_F17_F0(a0)
-   fld f18, TASK_THREAD_F18_F0(a0)
-   fld f19, TASK_THREAD_F19_F0(a0)
-   fld f20, TASK_THREAD_F20_F0(a0)
-   fld f21, TASK_THREAD_F21_F0(a0)
-   fld f22, TASK_THREAD_F22_F0(a0)
-   fld f23, TASK_THREAD_F23_F0(a0)
-   fld f24, TASK_THREAD_F24_F0(a0)
-   fld f25, TASK_THREAD_F25_F0(a0)
-   fld f26, TASK_THREAD_F26_F0(a0)
-   fld f27, TASK_THREAD_F27_F0(a0)
-   fld f28, TASK_THREAD_F28_F0(a0)
-   fld f29, TASK_THREAD_F29_F0(a0)
-   fld f30, TASK_THREAD_F30_F0(a0)
-   fld f31, TASK_THREAD_F31_F0(a0)
-   fscsr t0
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_restore)
-
-
.section ".rodata"
/* Exception vector table */
 ENTRY(excp_vect_table)
diff --git a/arch/riscv/kernel/fpu.S b/arch/riscv/kernel/fpu.S
new file mode 100644
index ..3210ef502e55
--- /dev/null
+++ b/arch/riscv/kernel/fpu.S
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2012 Regents of the University of California
+ * Copyright (C) 2017 SiFive
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+ENTRY(__fstate_save)
+   

[PATCH v3 4/4] Add an option to support no-FPU systems

2018-08-01 Thread Alan Kao
FP codes have been separated from common part in previous patches.
This patch add the CONFIG_FPU option and some stubs to support
no-FPU systems.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/Kconfig |  9 +
 arch/riscv/include/asm/switch_to.h | 12 
 arch/riscv/kernel/Makefile |  2 +-
 arch/riscv/kernel/process.c|  4 +++-
 arch/riscv/kernel/signal.c |  2 ++
 5 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 6debcc4afc72..6069597ba73f 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -232,6 +232,15 @@ config RISCV_BASE_PMU
 
 endmenu
 
+config FPU
+   bool "FPU support"
+   default y
+   help
+ Say N here if you want to disable all floating-point related procedure
+ in the kernel.
+
+ If you don't know what to do here, say Y.
+
 endmenu
 
 menu "Kernel type"
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index dd6b05bff75b..94a08d28ccf5 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -18,6 +18,7 @@
 #include 
 #include 
 
+#ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
 extern void __fstate_restore(struct task_struct *restore_from);
 
@@ -55,6 +56,17 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_restore(next, task_pt_regs(next));
 }
 
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_INITIAL)
+
+#else
+#define save_fp_state(task, regs) (0)
+#define restore_fp_state(task, regs) (0)
+#define fstate_save(task, regs) do { } while (0)
+#define fstate_restore(task, regs) do { } while (0)
+#define __switch_to_aux(__prev, __next) do { } while (0)
+#define DEFAULT_SSTATUS (SR_SPIE | SR_FS_OFF)
+#endif
+
 extern struct task_struct *__switch_to(struct task_struct *,
   struct task_struct *);
 
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index bd433efd915e..f13f7f276639 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,7 +13,6 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
-obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
@@ -32,6 +31,7 @@ obj-y += vdso/
 
 CFLAGS_setup.o := -mcmodel=medany
 
+obj-$(CONFIG_FPU)  += fpu.o
 obj-$(CONFIG_SMP)  += smpboot.o
 obj-$(CONFIG_SMP)  += smp.o
 obj-$(CONFIG_MODULES)  += module.o
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index cb209139ba53..3820d89e2db9 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -83,7 +83,7 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
+   regs->sstatus = DEFAULT_SSTATUS;
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
@@ -91,12 +91,14 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
 
 void flush_thread(void)
 {
+#ifdef CONFIG_FPU
/*
 * Reset FPU context
 *  frm: round to nearest, ties to even (IEEE default)
 *  fflags: accrued exceptions cleared
 */
memset(>thread.fstate, 0, sizeof(current->thread.fstate));
+#endif
 }
 
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index bfce852d5ddc..b7bbb5c33594 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,6 +37,7 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
+#ifdef CONFIG_FPU
 static long restore_fp_state(struct pt_regs *regs,
union __riscv_fp_state *sc_fpregs)
 {
@@ -85,6 +86,7 @@ static long save_fp_state(struct pt_regs *regs,
 
return err;
 }
+#endif
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
-- 
2.18.0



[PATCH v3 1/4] Extract FPU context operations from entry.S

2018-08-01 Thread Alan Kao
We move __fstate_save and __fstate_restore to a new source
file, fpu.S.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/entry.S  |  87 --
 arch/riscv/kernel/fpu.S| 105 +
 3 files changed, 106 insertions(+), 87 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index e1274fc03af4..bd433efd915e 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -13,6 +13,7 @@ extra-y += vmlinux.lds
 obj-y  += cpu.o
 obj-y  += cpufeature.o
 obj-y  += entry.o
+obj-y  += fpu.o
 obj-y  += irq.o
 obj-y  += process.o
 obj-y  += ptrace.o
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index 9aaf6c986771..edcd5920ee4e 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -357,93 +357,6 @@ ENTRY(__switch_to)
ret
 ENDPROC(__switch_to)
 
-ENTRY(__fstate_save)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   csrs sstatus, t1
-   frcsr t0
-   fsd f0,  TASK_THREAD_F0_F0(a0)
-   fsd f1,  TASK_THREAD_F1_F0(a0)
-   fsd f2,  TASK_THREAD_F2_F0(a0)
-   fsd f3,  TASK_THREAD_F3_F0(a0)
-   fsd f4,  TASK_THREAD_F4_F0(a0)
-   fsd f5,  TASK_THREAD_F5_F0(a0)
-   fsd f6,  TASK_THREAD_F6_F0(a0)
-   fsd f7,  TASK_THREAD_F7_F0(a0)
-   fsd f8,  TASK_THREAD_F8_F0(a0)
-   fsd f9,  TASK_THREAD_F9_F0(a0)
-   fsd f10, TASK_THREAD_F10_F0(a0)
-   fsd f11, TASK_THREAD_F11_F0(a0)
-   fsd f12, TASK_THREAD_F12_F0(a0)
-   fsd f13, TASK_THREAD_F13_F0(a0)
-   fsd f14, TASK_THREAD_F14_F0(a0)
-   fsd f15, TASK_THREAD_F15_F0(a0)
-   fsd f16, TASK_THREAD_F16_F0(a0)
-   fsd f17, TASK_THREAD_F17_F0(a0)
-   fsd f18, TASK_THREAD_F18_F0(a0)
-   fsd f19, TASK_THREAD_F19_F0(a0)
-   fsd f20, TASK_THREAD_F20_F0(a0)
-   fsd f21, TASK_THREAD_F21_F0(a0)
-   fsd f22, TASK_THREAD_F22_F0(a0)
-   fsd f23, TASK_THREAD_F23_F0(a0)
-   fsd f24, TASK_THREAD_F24_F0(a0)
-   fsd f25, TASK_THREAD_F25_F0(a0)
-   fsd f26, TASK_THREAD_F26_F0(a0)
-   fsd f27, TASK_THREAD_F27_F0(a0)
-   fsd f28, TASK_THREAD_F28_F0(a0)
-   fsd f29, TASK_THREAD_F29_F0(a0)
-   fsd f30, TASK_THREAD_F30_F0(a0)
-   fsd f31, TASK_THREAD_F31_F0(a0)
-   sw t0, TASK_THREAD_FCSR_F0(a0)
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_save)
-
-ENTRY(__fstate_restore)
-   li  a2,  TASK_THREAD_F0
-   add a0, a0, a2
-   li t1, SR_FS
-   lw t0, TASK_THREAD_FCSR_F0(a0)
-   csrs sstatus, t1
-   fld f0,  TASK_THREAD_F0_F0(a0)
-   fld f1,  TASK_THREAD_F1_F0(a0)
-   fld f2,  TASK_THREAD_F2_F0(a0)
-   fld f3,  TASK_THREAD_F3_F0(a0)
-   fld f4,  TASK_THREAD_F4_F0(a0)
-   fld f5,  TASK_THREAD_F5_F0(a0)
-   fld f6,  TASK_THREAD_F6_F0(a0)
-   fld f7,  TASK_THREAD_F7_F0(a0)
-   fld f8,  TASK_THREAD_F8_F0(a0)
-   fld f9,  TASK_THREAD_F9_F0(a0)
-   fld f10, TASK_THREAD_F10_F0(a0)
-   fld f11, TASK_THREAD_F11_F0(a0)
-   fld f12, TASK_THREAD_F12_F0(a0)
-   fld f13, TASK_THREAD_F13_F0(a0)
-   fld f14, TASK_THREAD_F14_F0(a0)
-   fld f15, TASK_THREAD_F15_F0(a0)
-   fld f16, TASK_THREAD_F16_F0(a0)
-   fld f17, TASK_THREAD_F17_F0(a0)
-   fld f18, TASK_THREAD_F18_F0(a0)
-   fld f19, TASK_THREAD_F19_F0(a0)
-   fld f20, TASK_THREAD_F20_F0(a0)
-   fld f21, TASK_THREAD_F21_F0(a0)
-   fld f22, TASK_THREAD_F22_F0(a0)
-   fld f23, TASK_THREAD_F23_F0(a0)
-   fld f24, TASK_THREAD_F24_F0(a0)
-   fld f25, TASK_THREAD_F25_F0(a0)
-   fld f26, TASK_THREAD_F26_F0(a0)
-   fld f27, TASK_THREAD_F27_F0(a0)
-   fld f28, TASK_THREAD_F28_F0(a0)
-   fld f29, TASK_THREAD_F29_F0(a0)
-   fld f30, TASK_THREAD_F30_F0(a0)
-   fld f31, TASK_THREAD_F31_F0(a0)
-   fscsr t0
-   csrc sstatus, t1
-   ret
-ENDPROC(__fstate_restore)
-
-
.section ".rodata"
/* Exception vector table */
 ENTRY(excp_vect_table)
diff --git a/arch/riscv/kernel/fpu.S b/arch/riscv/kernel/fpu.S
new file mode 100644
index ..3210ef502e55
--- /dev/null
+++ b/arch/riscv/kernel/fpu.S
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2012 Regents of the University of California
+ * Copyright (C) 2017 SiFive
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+ENTRY(__fstate_save)
+   

[PATCH v3 3/4] Cleanup ISA string setting

2018-08-01 Thread Alan Kao
The reason that we cannot follow the review's suggestion in
https://lkml.org/lkml/2018/6/21/39 is because using "+=" as the
connector in Makefile introduces blanks bewteen the left-hand
side alphabets.

Note: (Assume that atomic and compressed is on)

Before this patch, assembler was always given the riscv64imafdc
MARCH string because there are fld/fsd's in entry.S; compiler was
always given riscv64imac because kernel doesn't need floating point
code generation.  After this, the MARCH string in AFLAGS and CFLAGS
become the same.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/Makefile | 19 ---
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 6d4a5f6c3f4f..e0fe6790624f 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -26,7 +26,6 @@ ifeq ($(CONFIG_ARCH_RV64I),y)
 
KBUILD_CFLAGS += -mabi=lp64
KBUILD_AFLAGS += -mabi=lp64
-   KBUILD_MARCH = rv64im
LDFLAGS += -melf64lriscv
 else
BITS := 32
@@ -34,22 +33,20 @@ else
 
KBUILD_CFLAGS += -mabi=ilp32
KBUILD_AFLAGS += -mabi=ilp32
-   KBUILD_MARCH = rv32im
LDFLAGS += -melf32lriscv
 endif
 
 KBUILD_CFLAGS += -Wall
 
-ifeq ($(CONFIG_RISCV_ISA_A),y)
-   KBUILD_ARCH_A = a
-endif
-ifeq ($(CONFIG_RISCV_ISA_C),y)
-   KBUILD_ARCH_C = c
-endif
-
-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+# ISA string setting
+riscv-march-$(CONFIG_ARCH_RV32I)   := rv32im
+riscv-march-$(CONFIG_ARCH_RV64I)   := rv64im
+riscv-march-$(CONFIG_RISCV_ISA_A)  := $(riscv-march-y)a
+riscv-march-y  := $(riscv-march-y)fd
+riscv-march-$(CONFIG_RISCV_ISA_C)  := $(riscv-march-y)c
+KBUILD_CFLAGS += -march=$(riscv-march-y)
+KBUILD_AFLAGS += -march=$(riscv-march-y)
 
-KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
 KBUILD_CFLAGS += -mno-save-restore
 KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
 
-- 
2.18.0



[PATCH v3 0/4] riscv: Add support to no-FPU systems

2018-08-01 Thread Alan Kao
This patchset adds an option, CONFIG_FPU, to enable/disable floating-
point procedures.

Changes in v3:
 - Refactor the whole patch into independent ones.

Changes in v2:
 - Various code cleanups and style fixes.

Alan Kao (4):
  Extract FPU context operations from entry.S
  Refactor FPU codes in signal setup/return procedures
  Cleanup ISA string setting
  Add an option to support no-FPU systems

 arch/riscv/Kconfig |   9 +++
 arch/riscv/Makefile|  19 +++---
 arch/riscv/include/asm/switch_to.h |  12 
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/entry.S  |  87 
 arch/riscv/kernel/fpu.S| 105 +
 arch/riscv/kernel/process.c|   4 +-
 arch/riscv/kernel/signal.c |  70 +++
 8 files changed, 181 insertions(+), 126 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

-- 
2.18.0



[PATCH v3 2/4] Refactor FPU codes in signal setup/return procedures

2018-08-01 Thread Alan Kao
Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/kernel/signal.c | 68 +++---
 1 file changed, 41 insertions(+), 27 deletions(-)

diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 718d0c984ef0..bfce852d5ddc 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,45 +37,63 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
-static long restore_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long restore_fp_state(struct pt_regs *regs,
+   union __riscv_fp_state *sc_fpregs)
 {
long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
err = __copy_from_user(>thread.fstate, state, sizeof(*state));
-   if (likely(!err))
-   fstate_restore(current, regs);
+   if (unlikely(err))
+   return err;
+
+   fstate_restore(current, regs);
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   u32 value;
+
+   err = __get_user(value, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   if (value != 0)
+   return -EINVAL;
+   }
+
return err;
 }
 
-static long save_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long save_fp_state(struct pt_regs *regs,
+   union __riscv_fp_state *sc_fpregs)
 {
+   long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
fstate_save(current, regs);
-   return __copy_to_user(state, >thread.fstate, sizeof(*state));
+   err = __copy_to_user(state, >thread.fstate, sizeof(*state));
+   if (unlikely(err))
+   return err;
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs.q.reserved); i++) {
+   err = __put_user(0, _fpregs.q.reserved[i]);
+   if (unlikely(err))
+   break;
+   }
+
+   return err;
 }
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
 {
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
-   if (unlikely(err))
-   return err;
/* Restore the floating-point state. */
-   err = restore_d_state(regs, >sc_fpregs.d);
-   if (unlikely(err))
-   return err;
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) {
-   u32 value;
-   err = __get_user(value, >sc_fpregs.q.reserved[i]);
-   if (unlikely(err))
-   break;
-   if (value != 0)
-   return -EINVAL;
-   }
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -124,14 +142,10 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
 {
struct sigcontext __user *sc = >uc.uc_mcontext;
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_d_state(regs, >sc_fpregs.d);
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++)
-   err |= __put_user(0, >sc_fpregs.q.reserved[i]);
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.18.0



[PATCH v3 3/4] Cleanup ISA string setting

2018-08-01 Thread Alan Kao
The reason that we cannot follow the review's suggestion in
https://lkml.org/lkml/2018/6/21/39 is because using "+=" as the
connector in Makefile introduces blanks bewteen the left-hand
side alphabets.

Note: (Assume that atomic and compressed is on)

Before this patch, assembler was always given the riscv64imafdc
MARCH string because there are fld/fsd's in entry.S; compiler was
always given riscv64imac because kernel doesn't need floating point
code generation.  After this, the MARCH string in AFLAGS and CFLAGS
become the same.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/Makefile | 19 ---
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 6d4a5f6c3f4f..e0fe6790624f 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -26,7 +26,6 @@ ifeq ($(CONFIG_ARCH_RV64I),y)
 
KBUILD_CFLAGS += -mabi=lp64
KBUILD_AFLAGS += -mabi=lp64
-   KBUILD_MARCH = rv64im
LDFLAGS += -melf64lriscv
 else
BITS := 32
@@ -34,22 +33,20 @@ else
 
KBUILD_CFLAGS += -mabi=ilp32
KBUILD_AFLAGS += -mabi=ilp32
-   KBUILD_MARCH = rv32im
LDFLAGS += -melf32lriscv
 endif
 
 KBUILD_CFLAGS += -Wall
 
-ifeq ($(CONFIG_RISCV_ISA_A),y)
-   KBUILD_ARCH_A = a
-endif
-ifeq ($(CONFIG_RISCV_ISA_C),y)
-   KBUILD_ARCH_C = c
-endif
-
-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+# ISA string setting
+riscv-march-$(CONFIG_ARCH_RV32I)   := rv32im
+riscv-march-$(CONFIG_ARCH_RV64I)   := rv64im
+riscv-march-$(CONFIG_RISCV_ISA_A)  := $(riscv-march-y)a
+riscv-march-y  := $(riscv-march-y)fd
+riscv-march-$(CONFIG_RISCV_ISA_C)  := $(riscv-march-y)c
+KBUILD_CFLAGS += -march=$(riscv-march-y)
+KBUILD_AFLAGS += -march=$(riscv-march-y)
 
-KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
 KBUILD_CFLAGS += -mno-save-restore
 KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
 
-- 
2.18.0



[PATCH v3 0/4] riscv: Add support to no-FPU systems

2018-08-01 Thread Alan Kao
This patchset adds an option, CONFIG_FPU, to enable/disable floating-
point procedures.

Changes in v3:
 - Refactor the whole patch into independent ones.

Changes in v2:
 - Various code cleanups and style fixes.

Alan Kao (4):
  Extract FPU context operations from entry.S
  Refactor FPU codes in signal setup/return procedures
  Cleanup ISA string setting
  Add an option to support no-FPU systems

 arch/riscv/Kconfig |   9 +++
 arch/riscv/Makefile|  19 +++---
 arch/riscv/include/asm/switch_to.h |  12 
 arch/riscv/kernel/Makefile |   1 +
 arch/riscv/kernel/entry.S  |  87 
 arch/riscv/kernel/fpu.S| 105 +
 arch/riscv/kernel/process.c|   4 +-
 arch/riscv/kernel/signal.c |  70 +++
 8 files changed, 181 insertions(+), 126 deletions(-)
 create mode 100644 arch/riscv/kernel/fpu.S

-- 
2.18.0



[PATCH v3 2/4] Refactor FPU codes in signal setup/return procedures

2018-08-01 Thread Alan Kao
Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Vincent Chen 
Cc: Zong Li 
Cc: Nick Hu 
---
 arch/riscv/kernel/signal.c | 68 +++---
 1 file changed, 41 insertions(+), 27 deletions(-)

diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 718d0c984ef0..bfce852d5ddc 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,45 +37,63 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
-static long restore_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long restore_fp_state(struct pt_regs *regs,
+   union __riscv_fp_state *sc_fpregs)
 {
long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
err = __copy_from_user(>thread.fstate, state, sizeof(*state));
-   if (likely(!err))
-   fstate_restore(current, regs);
+   if (unlikely(err))
+   return err;
+
+   fstate_restore(current, regs);
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
+   u32 value;
+
+   err = __get_user(value, _fpregs->q.reserved[i]);
+   if (unlikely(err))
+   break;
+   if (value != 0)
+   return -EINVAL;
+   }
+
return err;
 }
 
-static long save_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+static long save_fp_state(struct pt_regs *regs,
+   union __riscv_fp_state *sc_fpregs)
 {
+   long err;
+   struct __riscv_d_ext_state __user *state = _fpregs->d;
+   size_t i;
+
fstate_save(current, regs);
-   return __copy_to_user(state, >thread.fstate, sizeof(*state));
+   err = __copy_to_user(state, >thread.fstate, sizeof(*state));
+   if (unlikely(err))
+   return err;
+
+   /* We support no other extension state at this time. */
+   for (i = 0; i < ARRAY_SIZE(sc_fpregs.q.reserved); i++) {
+   err = __put_user(0, _fpregs.q.reserved[i]);
+   if (unlikely(err))
+   break;
+   }
+
+   return err;
 }
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
 {
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
-   if (unlikely(err))
-   return err;
/* Restore the floating-point state. */
-   err = restore_d_state(regs, >sc_fpregs.d);
-   if (unlikely(err))
-   return err;
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) {
-   u32 value;
-   err = __get_user(value, >sc_fpregs.q.reserved[i]);
-   if (unlikely(err))
-   break;
-   if (value != 0)
-   return -EINVAL;
-   }
+   err |= restore_fp_state(regs, >sc_fpregs);
return err;
 }
 
@@ -124,14 +142,10 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
 {
struct sigcontext __user *sc = >uc.uc_mcontext;
long err;
-   size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
-   err |= save_d_state(regs, >sc_fpregs.d);
-   /* We support no other extension state at this time. */
-   for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++)
-   err |= __put_user(0, >sc_fpregs.q.reserved[i]);
+   err |= save_fp_state(regs, >sc_fpregs);
return err;
 }
 
-- 
2.18.0



Re: [PATCH v2] riscv: Add support to no-FPU systems

2018-08-01 Thread Alan Kao
On Wed, Aug 01, 2018 at 10:55:28AM -0700, Palmer Dabbelt wrote:
> On Tue, 26 Jun 2018 21:22:26 PDT (-0700), alan...@andestech.com wrote:
> >This patch adds an option, CONFIG_FPU, to enable/disable floating
> >procedures.  Also, some style issues are fixed.
> >
> >Signed-off-by: Alan Kao 
> >Cc: Greentime Hu 
> >Cc: Zong Li 
> >---
> > arch/riscv/Kconfig |  9 
> > arch/riscv/Makefile| 19 +++
> > arch/riscv/include/asm/switch_to.h |  6 +++
> > arch/riscv/kernel/entry.S  |  3 +-
> > arch/riscv/kernel/process.c|  7 ++-
> > arch/riscv/kernel/signal.c | 82 +-
> > 6 files changed, 90 insertions(+), 36 deletions(-)
> >
> >diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> >index 6debcc4afc72..6069597ba73f 100644
> >--- a/arch/riscv/Kconfig
> >+++ b/arch/riscv/Kconfig
> >@@ -232,6 +232,15 @@ config RISCV_BASE_PMU
> >
> > endmenu
> >
> >+config FPU
> >+bool "FPU support"
> >+default y
> >+help
> >+  Say N here if you want to disable all floating-point related procedure
> >+  in the kernel.
> >+
> >+  If you don't know what to do here, say Y.
> >+
> > endmenu
> 
> Sorry for letting this slide for a bit.  While I'm not opposed to a solution
> that requires a FPU Kconfig option, it'd be a bit better if we could detect
> this at boot time.  I think this should be possible because at one point
> this actually worked and we could boot the same kernel on FPU and no-FPU
> systems.
> 
> If that's not possible then we'll have to take something like this.  There
> were some comments on this v2 but I don't see a v3, did I miss one?

I have been refatoring this into a patchset containing logically
indenpendent patches.  It will be sent soon after some sanity checks.


Re: [PATCH v2] riscv: Add support to no-FPU systems

2018-08-01 Thread Alan Kao
On Wed, Aug 01, 2018 at 10:55:28AM -0700, Palmer Dabbelt wrote:
> On Tue, 26 Jun 2018 21:22:26 PDT (-0700), alan...@andestech.com wrote:
> >This patch adds an option, CONFIG_FPU, to enable/disable floating
> >procedures.  Also, some style issues are fixed.
> >
> >Signed-off-by: Alan Kao 
> >Cc: Greentime Hu 
> >Cc: Zong Li 
> >---
> > arch/riscv/Kconfig |  9 
> > arch/riscv/Makefile| 19 +++
> > arch/riscv/include/asm/switch_to.h |  6 +++
> > arch/riscv/kernel/entry.S  |  3 +-
> > arch/riscv/kernel/process.c|  7 ++-
> > arch/riscv/kernel/signal.c | 82 +-
> > 6 files changed, 90 insertions(+), 36 deletions(-)
> >
> >diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> >index 6debcc4afc72..6069597ba73f 100644
> >--- a/arch/riscv/Kconfig
> >+++ b/arch/riscv/Kconfig
> >@@ -232,6 +232,15 @@ config RISCV_BASE_PMU
> >
> > endmenu
> >
> >+config FPU
> >+bool "FPU support"
> >+default y
> >+help
> >+  Say N here if you want to disable all floating-point related procedure
> >+  in the kernel.
> >+
> >+  If you don't know what to do here, say Y.
> >+
> > endmenu
> 
> Sorry for letting this slide for a bit.  While I'm not opposed to a solution
> that requires a FPU Kconfig option, it'd be a bit better if we could detect
> this at boot time.  I think this should be possible because at one point
> this actually worked and we could boot the same kernel on FPU and no-FPU
> systems.
> 
> If that's not possible then we'll have to take something like this.  There
> were some comments on this v2 but I don't see a v3, did I miss one?

I have been refatoring this into a patchset containing logically
indenpendent patches.  It will be sent soon after some sanity checks.


[PATCH v2] riscv: Add support to no-FPU systems

2018-06-26 Thread Alan Kao
This patch adds an option, CONFIG_FPU, to enable/disable floating
procedures.  Also, some style issues are fixed.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Zong Li 
---
 arch/riscv/Kconfig |  9 
 arch/riscv/Makefile| 19 +++
 arch/riscv/include/asm/switch_to.h |  6 +++
 arch/riscv/kernel/entry.S  |  3 +-
 arch/riscv/kernel/process.c|  7 ++-
 arch/riscv/kernel/signal.c | 82 +-
 6 files changed, 90 insertions(+), 36 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 6debcc4afc72..6069597ba73f 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -232,6 +232,15 @@ config RISCV_BASE_PMU
 
 endmenu
 
+config FPU
+   bool "FPU support"
+   default y
+   help
+ Say N here if you want to disable all floating-point related procedure
+ in the kernel.
+
+ If you don't know what to do here, say Y.
+
 endmenu
 
 menu "Kernel type"
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 6d4a5f6c3f4f..ad3033739430 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -26,7 +26,6 @@ ifeq ($(CONFIG_ARCH_RV64I),y)
 
KBUILD_CFLAGS += -mabi=lp64
KBUILD_AFLAGS += -mabi=lp64
-   KBUILD_MARCH = rv64im
LDFLAGS += -melf64lriscv
 else
BITS := 32
@@ -34,22 +33,20 @@ else
 
KBUILD_CFLAGS += -mabi=ilp32
KBUILD_AFLAGS += -mabi=ilp32
-   KBUILD_MARCH = rv32im
LDFLAGS += -melf32lriscv
 endif
 
 KBUILD_CFLAGS += -Wall
 
-ifeq ($(CONFIG_RISCV_ISA_A),y)
-   KBUILD_ARCH_A = a
-endif
-ifeq ($(CONFIG_RISCV_ISA_C),y)
-   KBUILD_ARCH_C = c
-endif
-
-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+# ISA string setting
+riscv-march-$(CONFIG_ARCH_RV32I)  := rv32im
+riscv-march-$(CONFIG_ARCH_RV64I)  := rv64im
+riscv-march-$(CONFIG_RISCV_ISA_A) := $(riscv-march-y)a
+riscv-march-$(CONFIG_FPU) := $(riscv-march-y)fd
+riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c
+KBUILD_CFLAGS += -march=$(riscv-march-y)
+KBUILD_AFLAGS += -march=$(riscv-march-y)
 
-KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
 KBUILD_CFLAGS += -mno-save-restore
 KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
 
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index dd6b05bff75b..de333c012227 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -18,6 +18,7 @@
 #include 
 #include 
 
+#ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
 extern void __fstate_restore(struct task_struct *restore_from);
 
@@ -54,6 +55,11 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_save(prev, regs);
fstate_restore(next, task_pt_regs(next));
 }
+#else
+#define fstate_save(task, regs) do { } while (0)
+#define fstate_restore(task, regs) do { } while (0)
+#define __switch_to_aux(__prev, __next)
+#endif
 
 extern struct task_struct *__switch_to(struct task_struct *,
   struct task_struct *);
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index 9aaf6c986771..89867c9aa4f5 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -357,6 +357,7 @@ ENTRY(__switch_to)
ret
 ENDPROC(__switch_to)
 
+#ifdef CONFIG_FPU
 ENTRY(__fstate_save)
li  a2,  TASK_THREAD_F0
add a0, a0, a2
@@ -442,7 +443,7 @@ ENTRY(__fstate_restore)
csrc sstatus, t1
ret
 ENDPROC(__fstate_restore)
-
+#endif
 
.section ".rodata"
/* Exception vector table */
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index cb209139ba53..99d20283bb62 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -83,7 +83,12 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
+   /* User mode, irqs on */
+#ifdef CONFIG_FPU
+   regs->sstatus = SR_SPIE | SR_FS_INITIAL;
+#else
+   regs->sstatus = SR_SPIE | SR_FS_OFF;
+#endif
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 718d0c984ef0..a7a5ed5598a8 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,8 +37,9 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
-static long restore_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+#ifdef CONFIG_FPU
+static inline long __restore_d_state(struct pt_regs *regs,
+struct __riscv_d_ext_state __user *state)
 {
long err;
err = __copy_from_user(>thread.fstate, state, sizeof(*state));
@@ -47,35 +48,75 @@ 

[PATCH v2] riscv: Add support to no-FPU systems

2018-06-26 Thread Alan Kao
This patch adds an option, CONFIG_FPU, to enable/disable floating
procedures.  Also, some style issues are fixed.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Zong Li 
---
 arch/riscv/Kconfig |  9 
 arch/riscv/Makefile| 19 +++
 arch/riscv/include/asm/switch_to.h |  6 +++
 arch/riscv/kernel/entry.S  |  3 +-
 arch/riscv/kernel/process.c|  7 ++-
 arch/riscv/kernel/signal.c | 82 +-
 6 files changed, 90 insertions(+), 36 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 6debcc4afc72..6069597ba73f 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -232,6 +232,15 @@ config RISCV_BASE_PMU
 
 endmenu
 
+config FPU
+   bool "FPU support"
+   default y
+   help
+ Say N here if you want to disable all floating-point related procedure
+ in the kernel.
+
+ If you don't know what to do here, say Y.
+
 endmenu
 
 menu "Kernel type"
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 6d4a5f6c3f4f..ad3033739430 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -26,7 +26,6 @@ ifeq ($(CONFIG_ARCH_RV64I),y)
 
KBUILD_CFLAGS += -mabi=lp64
KBUILD_AFLAGS += -mabi=lp64
-   KBUILD_MARCH = rv64im
LDFLAGS += -melf64lriscv
 else
BITS := 32
@@ -34,22 +33,20 @@ else
 
KBUILD_CFLAGS += -mabi=ilp32
KBUILD_AFLAGS += -mabi=ilp32
-   KBUILD_MARCH = rv32im
LDFLAGS += -melf32lriscv
 endif
 
 KBUILD_CFLAGS += -Wall
 
-ifeq ($(CONFIG_RISCV_ISA_A),y)
-   KBUILD_ARCH_A = a
-endif
-ifeq ($(CONFIG_RISCV_ISA_C),y)
-   KBUILD_ARCH_C = c
-endif
-
-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+# ISA string setting
+riscv-march-$(CONFIG_ARCH_RV32I)  := rv32im
+riscv-march-$(CONFIG_ARCH_RV64I)  := rv64im
+riscv-march-$(CONFIG_RISCV_ISA_A) := $(riscv-march-y)a
+riscv-march-$(CONFIG_FPU) := $(riscv-march-y)fd
+riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c
+KBUILD_CFLAGS += -march=$(riscv-march-y)
+KBUILD_AFLAGS += -march=$(riscv-march-y)
 
-KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
 KBUILD_CFLAGS += -mno-save-restore
 KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
 
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index dd6b05bff75b..de333c012227 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -18,6 +18,7 @@
 #include 
 #include 
 
+#ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
 extern void __fstate_restore(struct task_struct *restore_from);
 
@@ -54,6 +55,11 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_save(prev, regs);
fstate_restore(next, task_pt_regs(next));
 }
+#else
+#define fstate_save(task, regs) do { } while (0)
+#define fstate_restore(task, regs) do { } while (0)
+#define __switch_to_aux(__prev, __next)
+#endif
 
 extern struct task_struct *__switch_to(struct task_struct *,
   struct task_struct *);
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index 9aaf6c986771..89867c9aa4f5 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -357,6 +357,7 @@ ENTRY(__switch_to)
ret
 ENDPROC(__switch_to)
 
+#ifdef CONFIG_FPU
 ENTRY(__fstate_save)
li  a2,  TASK_THREAD_F0
add a0, a0, a2
@@ -442,7 +443,7 @@ ENTRY(__fstate_restore)
csrc sstatus, t1
ret
 ENDPROC(__fstate_restore)
-
+#endif
 
.section ".rodata"
/* Exception vector table */
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index cb209139ba53..99d20283bb62 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -83,7 +83,12 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
-   regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
+   /* User mode, irqs on */
+#ifdef CONFIG_FPU
+   regs->sstatus = SR_SPIE | SR_FS_INITIAL;
+#else
+   regs->sstatus = SR_SPIE | SR_FS_OFF;
+#endif
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 718d0c984ef0..a7a5ed5598a8 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,8 +37,9 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
-static long restore_d_state(struct pt_regs *regs,
-   struct __riscv_d_ext_state __user *state)
+#ifdef CONFIG_FPU
+static inline long __restore_d_state(struct pt_regs *regs,
+struct __riscv_d_ext_state __user *state)
 {
long err;
err = __copy_from_user(>thread.fstate, state, sizeof(*state));
@@ -47,35 +48,75 @@ 

Re: [PATCH] riscv: Add support to no-FPU systems

2018-06-21 Thread Alan Kao
On Wed, Jun 20, 2018 at 11:39:38PM -0700, Christoph Hellwig wrote:
> > +ifeq ($(CONFIG_FPU),y)
> >  KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
> > +else
> > +KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
> > +endif
> 
> Can we refactor that KBUILD_ARCH code into something like
> 
> riscv-march-y :=
> riscv-march-$(CONFIG_ARCH_RV32I)  += rv32im
> riscv-march-$(CONFIG_ARCH_RV64I)  += rv64im
> riscv-march-$(CONFIG_RISCV_ISA_A) += a
> riscv-march-$(CONFIG_FPU) += fd
> riscv-march-$(CONFIG_RISCV_ISA_C) += c
> 
> KBUILD_CFLAGS += -march=$(riscv-march-y)
> 

That's neat, sure.

> > +#ifdef CONFIG_FPU
> > regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
> > +#else
> > +   regs->sstatus = SR_SPIE | SR_FS_OFF;
> > +#endif
> 
> Having the comment in one branch, but not the other is odd.  I'd be
> tempted to just remove t entirely, but if not it should be move up
> or duplicated.
> 

I'll move that comment up.

> >  int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
> >  {
> > +#ifdef CONFIG_FPU
> > fstate_save(src, task_pt_regs(src));
> > +#endif
> 
> Please provide a !CONFIG_FPU stub for fstate_save, please.
> 
> >  }

It's OK to do this to fstate_save/restore, and

> > +#endif
> >  
> >  static long restore_sigcontext(struct pt_regs *regs,
> > struct sigcontext __user *sc)
> > @@ -63,6 +65,7 @@ static long restore_sigcontext(struct pt_regs *regs,
> > err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
> > if (unlikely(err))
> > return err;
> > +#ifdef CONFIG_FPU
> > /* Restore the floating-point state. */
> > err = restore_d_state(regs, >sc_fpregs.d);
> > if (unlikely(err))
> > @@ -76,6 +79,7 @@ static long restore_sigcontext(struct pt_regs *regs,
> > if (value != 0)
> > return -EINVAL;
> > }
> > +#endif
> 
> Same here.
> 

it's also OK to do so to restore_d_state/save_d_state.  But what to do with the
following __get_user/__put_user calls?

Can I rename existing restore_d_state to __restore_d_state, and create a new
function restore_d_state which includes the original restore_d_state/__get_user
pair, and the same to save_d_state?

> > @@ -127,11 +131,13 @@ static long setup_sigcontext(struct rt_sigframe 
> > __user *frame,
> > size_t i;
> > /* sc_regs is structured the same as the start of pt_regs */
> > err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
> > +#ifdef CONFIG_FPU
> > /* Save the floating-point state. */
> > err |= save_d_state(regs, >sc_fpregs.d);
> > /* We support no other extension state at this time. */
> > for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++)
> > err |= __put_user(0, >sc_fpregs.q.reserved[i]);
> > +#endif
> 
> Same here.
> 

Thanks,
Alan


Re: [PATCH] riscv: Add support to no-FPU systems

2018-06-21 Thread Alan Kao
On Wed, Jun 20, 2018 at 11:39:38PM -0700, Christoph Hellwig wrote:
> > +ifeq ($(CONFIG_FPU),y)
> >  KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
> > +else
> > +KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
> > +endif
> 
> Can we refactor that KBUILD_ARCH code into something like
> 
> riscv-march-y :=
> riscv-march-$(CONFIG_ARCH_RV32I)  += rv32im
> riscv-march-$(CONFIG_ARCH_RV64I)  += rv64im
> riscv-march-$(CONFIG_RISCV_ISA_A) += a
> riscv-march-$(CONFIG_FPU) += fd
> riscv-march-$(CONFIG_RISCV_ISA_C) += c
> 
> KBUILD_CFLAGS += -march=$(riscv-march-y)
> 

That's neat, sure.

> > +#ifdef CONFIG_FPU
> > regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
> > +#else
> > +   regs->sstatus = SR_SPIE | SR_FS_OFF;
> > +#endif
> 
> Having the comment in one branch, but not the other is odd.  I'd be
> tempted to just remove t entirely, but if not it should be move up
> or duplicated.
> 

I'll move that comment up.

> >  int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
> >  {
> > +#ifdef CONFIG_FPU
> > fstate_save(src, task_pt_regs(src));
> > +#endif
> 
> Please provide a !CONFIG_FPU stub for fstate_save, please.
> 
> >  }

It's OK to do this to fstate_save/restore, and

> > +#endif
> >  
> >  static long restore_sigcontext(struct pt_regs *regs,
> > struct sigcontext __user *sc)
> > @@ -63,6 +65,7 @@ static long restore_sigcontext(struct pt_regs *regs,
> > err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
> > if (unlikely(err))
> > return err;
> > +#ifdef CONFIG_FPU
> > /* Restore the floating-point state. */
> > err = restore_d_state(regs, >sc_fpregs.d);
> > if (unlikely(err))
> > @@ -76,6 +79,7 @@ static long restore_sigcontext(struct pt_regs *regs,
> > if (value != 0)
> > return -EINVAL;
> > }
> > +#endif
> 
> Same here.
> 

it's also OK to do so to restore_d_state/save_d_state.  But what to do with the
following __get_user/__put_user calls?

Can I rename existing restore_d_state to __restore_d_state, and create a new
function restore_d_state which includes the original restore_d_state/__get_user
pair, and the same to save_d_state?

> > @@ -127,11 +131,13 @@ static long setup_sigcontext(struct rt_sigframe 
> > __user *frame,
> > size_t i;
> > /* sc_regs is structured the same as the start of pt_regs */
> > err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
> > +#ifdef CONFIG_FPU
> > /* Save the floating-point state. */
> > err |= save_d_state(regs, >sc_fpregs.d);
> > /* We support no other extension state at this time. */
> > for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++)
> > err |= __put_user(0, >sc_fpregs.q.reserved[i]);
> > +#endif
> 
> Same here.
> 

Thanks,
Alan


[PATCH] riscv: Add support to no-FPU systems

2018-06-20 Thread Alan Kao
This patch adds an option, CONFIG_FPU, so that we can enable/disable
floating procedures in kernel.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Zong Li 
---
 arch/riscv/Kconfig | 4 
 arch/riscv/Makefile| 4 
 arch/riscv/include/asm/switch_to.h | 4 
 arch/riscv/kernel/entry.S  | 3 ++-
 arch/riscv/kernel/process.c| 6 ++
 arch/riscv/kernel/signal.c | 6 ++
 6 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 6debcc4afc72..429d0bf777c9 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -232,6 +232,10 @@ config RISCV_BASE_PMU
 
 endmenu
 
+config FPU
+   bool "FPU support"
+   default y
+
 endmenu
 
 menu "Kernel type"
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 76e958a5414a..2719e768c4dc 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -47,7 +47,11 @@ ifeq ($(CONFIG_RISCV_ISA_C),y)
KBUILD_ARCH_C = c
 endif
 
+ifeq ($(CONFIG_FPU),y)
 KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+else
+KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
+endif
 
 KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
 KBUILD_CFLAGS += -mno-save-restore
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index dd6b05bff75b..da0327a74466 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -18,6 +18,7 @@
 #include 
 #include 
 
+#ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
 extern void __fstate_restore(struct task_struct *restore_from);
 
@@ -54,6 +55,9 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_save(prev, regs);
fstate_restore(next, task_pt_regs(next));
 }
+#else
+#define __switch_to_aux(__prev, __next)
+#endif
 
 extern struct task_struct *__switch_to(struct task_struct *,
   struct task_struct *);
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index 9aaf6c986771..89867c9aa4f5 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -357,6 +357,7 @@ ENTRY(__switch_to)
ret
 ENDPROC(__switch_to)
 
+#ifdef CONFIG_FPU
 ENTRY(__fstate_save)
li  a2,  TASK_THREAD_F0
add a0, a0, a2
@@ -442,7 +443,7 @@ ENTRY(__fstate_restore)
csrc sstatus, t1
ret
 ENDPROC(__fstate_restore)
-
+#endif
 
.section ".rodata"
/* Exception vector table */
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index cb209139ba53..a817046e478a 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -83,7 +83,11 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
+#ifdef CONFIG_FPU
regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
+#else
+   regs->sstatus = SR_SPIE | SR_FS_OFF;
+#endif
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
@@ -101,7 +105,9 @@ void flush_thread(void)
 
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 {
+#ifdef CONFIG_FPU
fstate_save(src, task_pt_regs(src));
+#endif
*dst = *src;
return 0;
 }
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 718d0c984ef0..0f659c9ef465 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,6 +37,7 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
+#ifdef CONFIG_FPU
 static long restore_d_state(struct pt_regs *regs,
struct __riscv_d_ext_state __user *state)
 {
@@ -53,6 +54,7 @@ static long save_d_state(struct pt_regs *regs,
fstate_save(current, regs);
return __copy_to_user(state, >thread.fstate, sizeof(*state));
 }
+#endif
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
@@ -63,6 +65,7 @@ static long restore_sigcontext(struct pt_regs *regs,
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
if (unlikely(err))
return err;
+#ifdef CONFIG_FPU
/* Restore the floating-point state. */
err = restore_d_state(regs, >sc_fpregs.d);
if (unlikely(err))
@@ -76,6 +79,7 @@ static long restore_sigcontext(struct pt_regs *regs,
if (value != 0)
return -EINVAL;
}
+#endif
return err;
 }
 
@@ -127,11 +131,13 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
+#ifdef CONFIG_FPU
/* Save the floating-point state. */
err |= save_d_state(regs, >sc_fpregs.d);
/* We support no other extensi

[PATCH] riscv: Add support to no-FPU systems

2018-06-20 Thread Alan Kao
This patch adds an option, CONFIG_FPU, so that we can enable/disable
floating procedures in kernel.

Signed-off-by: Alan Kao 
Cc: Greentime Hu 
Cc: Zong Li 
---
 arch/riscv/Kconfig | 4 
 arch/riscv/Makefile| 4 
 arch/riscv/include/asm/switch_to.h | 4 
 arch/riscv/kernel/entry.S  | 3 ++-
 arch/riscv/kernel/process.c| 6 ++
 arch/riscv/kernel/signal.c | 6 ++
 6 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 6debcc4afc72..429d0bf777c9 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -232,6 +232,10 @@ config RISCV_BASE_PMU
 
 endmenu
 
+config FPU
+   bool "FPU support"
+   default y
+
 endmenu
 
 menu "Kernel type"
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 76e958a5414a..2719e768c4dc 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -47,7 +47,11 @@ ifeq ($(CONFIG_RISCV_ISA_C),y)
KBUILD_ARCH_C = c
 endif
 
+ifeq ($(CONFIG_FPU),y)
 KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C)
+else
+KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
+endif
 
 KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)
 KBUILD_CFLAGS += -mno-save-restore
diff --git a/arch/riscv/include/asm/switch_to.h 
b/arch/riscv/include/asm/switch_to.h
index dd6b05bff75b..da0327a74466 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -18,6 +18,7 @@
 #include 
 #include 
 
+#ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
 extern void __fstate_restore(struct task_struct *restore_from);
 
@@ -54,6 +55,9 @@ static inline void __switch_to_aux(struct task_struct *prev,
fstate_save(prev, regs);
fstate_restore(next, task_pt_regs(next));
 }
+#else
+#define __switch_to_aux(__prev, __next)
+#endif
 
 extern struct task_struct *__switch_to(struct task_struct *,
   struct task_struct *);
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index 9aaf6c986771..89867c9aa4f5 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -357,6 +357,7 @@ ENTRY(__switch_to)
ret
 ENDPROC(__switch_to)
 
+#ifdef CONFIG_FPU
 ENTRY(__fstate_save)
li  a2,  TASK_THREAD_F0
add a0, a0, a2
@@ -442,7 +443,7 @@ ENTRY(__fstate_restore)
csrc sstatus, t1
ret
 ENDPROC(__fstate_restore)
-
+#endif
 
.section ".rodata"
/* Exception vector table */
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index cb209139ba53..a817046e478a 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -83,7 +83,11 @@ void show_regs(struct pt_regs *regs)
 void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
 {
+#ifdef CONFIG_FPU
regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
+#else
+   regs->sstatus = SR_SPIE | SR_FS_OFF;
+#endif
regs->sepc = pc;
regs->sp = sp;
set_fs(USER_DS);
@@ -101,7 +105,9 @@ void flush_thread(void)
 
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 {
+#ifdef CONFIG_FPU
fstate_save(src, task_pt_regs(src));
+#endif
*dst = *src;
return 0;
 }
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 718d0c984ef0..0f659c9ef465 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -37,6 +37,7 @@ struct rt_sigframe {
struct ucontext uc;
 };
 
+#ifdef CONFIG_FPU
 static long restore_d_state(struct pt_regs *regs,
struct __riscv_d_ext_state __user *state)
 {
@@ -53,6 +54,7 @@ static long save_d_state(struct pt_regs *regs,
fstate_save(current, regs);
return __copy_to_user(state, >thread.fstate, sizeof(*state));
 }
+#endif
 
 static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
@@ -63,6 +65,7 @@ static long restore_sigcontext(struct pt_regs *regs,
err = __copy_from_user(regs, >sc_regs, sizeof(sc->sc_regs));
if (unlikely(err))
return err;
+#ifdef CONFIG_FPU
/* Restore the floating-point state. */
err = restore_d_state(regs, >sc_fpregs.d);
if (unlikely(err))
@@ -76,6 +79,7 @@ static long restore_sigcontext(struct pt_regs *regs,
if (value != 0)
return -EINVAL;
}
+#endif
return err;
 }
 
@@ -127,11 +131,13 @@ static long setup_sigcontext(struct rt_sigframe __user 
*frame,
size_t i;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(>sc_regs, regs, sizeof(sc->sc_regs));
+#ifdef CONFIG_FPU
/* Save the floating-point state. */
err |= save_d_state(regs, >sc_fpregs.d);
/* We support no other extensi

Re: [PATCH] riscv/ftrace: Export _mcount when FUNCTION_GRAPH_TRACER isn't set

2018-06-04 Thread Alan Kao
Hi Palmer,

Thanks for the refining work! But a small correction here:

On Mon, Jun 04, 2018 at 01:30:28PM -0700, Palmer Dabbelt wrote:
> From: Alan Kao 
> 
> The EXPORT_SYMBOL(_mcount) for RISC-V ended up inside a
> CONFIG_FUNCTION_GRAPH_TRACER ifdef.  If you enable modules without
> enabling CONFIG_FUNCTION_GRAPH_TRACER then you'll get a build error
> without this patch because the modules won't be able to find _mcount.

the export was inside a CONFIG_DYNAMIC_FTRACE section instead of
CONFIG_FUNCTION_GRAPH_TRACER.

> The new behavior is to export _mcount whenever CONFIG_FUNCTION_TRACER is
> defined.  This matches what every other architecture is doing.

Also, this patch is just a workaround and there are still issues in bringing
up ftrace for modules.  For details, please check previous emails between
Steve and me.

Thanks again for this better commit message.
Alan Kao

> 
> Signed-off-by: Alan Kao 
> Cc: Greentime Hu 
> Cc: Zong Li 
> Signed-off-by: Palmer Dabbelt 
> ---
>  arch/riscv/kernel/mcount.S | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/riscv/kernel/mcount.S b/arch/riscv/kernel/mcount.S
> index ce9bdc57a2a1..5721624886a1 100644
> --- a/arch/riscv/kernel/mcount.S
> +++ b/arch/riscv/kernel/mcount.S
> @@ -126,5 +126,5 @@ do_trace:
>   RESTORE_ABI_STATE
>   ret
>  ENDPROC(_mcount)
> -EXPORT_SYMBOL(_mcount)
>  #endif
> +EXPORT_SYMBOL(_mcount)
> -- 
> 2.16.4
> 


Re: [PATCH] riscv/ftrace: Export _mcount when FUNCTION_GRAPH_TRACER isn't set

2018-06-04 Thread Alan Kao
Hi Palmer,

Thanks for the refining work! But a small correction here:

On Mon, Jun 04, 2018 at 01:30:28PM -0700, Palmer Dabbelt wrote:
> From: Alan Kao 
> 
> The EXPORT_SYMBOL(_mcount) for RISC-V ended up inside a
> CONFIG_FUNCTION_GRAPH_TRACER ifdef.  If you enable modules without
> enabling CONFIG_FUNCTION_GRAPH_TRACER then you'll get a build error
> without this patch because the modules won't be able to find _mcount.

the export was inside a CONFIG_DYNAMIC_FTRACE section instead of
CONFIG_FUNCTION_GRAPH_TRACER.

> The new behavior is to export _mcount whenever CONFIG_FUNCTION_TRACER is
> defined.  This matches what every other architecture is doing.

Also, this patch is just a workaround and there are still issues in bringing
up ftrace for modules.  For details, please check previous emails between
Steve and me.

Thanks again for this better commit message.
Alan Kao

> 
> Signed-off-by: Alan Kao 
> Cc: Greentime Hu 
> Cc: Zong Li 
> Signed-off-by: Palmer Dabbelt 
> ---
>  arch/riscv/kernel/mcount.S | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/riscv/kernel/mcount.S b/arch/riscv/kernel/mcount.S
> index ce9bdc57a2a1..5721624886a1 100644
> --- a/arch/riscv/kernel/mcount.S
> +++ b/arch/riscv/kernel/mcount.S
> @@ -126,5 +126,5 @@ do_trace:
>   RESTORE_ABI_STATE
>   ret
>  ENDPROC(_mcount)
> -EXPORT_SYMBOL(_mcount)
>  #endif
> +EXPORT_SYMBOL(_mcount)
> -- 
> 2.16.4
> 


Re: [PATCH] riscv/ftrace: Fix the problem modules cannot find _mcount

2018-05-08 Thread Alan Kao
On Tue, May 08, 2018 at 09:11:42AM -0400, Steven Rostedt wrote:
> On Tue, 8 May 2018 11:21:57 +0800
> Alan Kao <alan...@andestech.com> wrote:
> 
> > Enabling ftrace and module support at the same time fails the kernel
> > build process, because modules cannot find the _mcount symbol.  This
> > patch fixes this issue.
> 
> I think you have a much bigger issue.
>

Yes, we do, but not this one.  Let me state more detail later.
 
> > 
> > Signed-off-by: Alan Kao <alan...@andestech.com>
> > Cc: Greentime Hu <greent...@andestech.com>
> > Cc: Zong Li <z...@andestech.com>
> > ---
> >  arch/riscv/kernel/mcount.S | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/arch/riscv/kernel/mcount.S b/arch/riscv/kernel/mcount.S
> > index ce9bdc57a2a1..5721624886a1 100644
> > --- a/arch/riscv/kernel/mcount.S
> > +++ b/arch/riscv/kernel/mcount.S
> > @@ -126,5 +126,5 @@ do_trace:
> > RESTORE_ABI_STATE
> > ret
> >  ENDPROC(_mcount)
> > -EXPORT_SYMBOL(_mcount)
> >  #endif
> > +EXPORT_SYMBOL(_mcount)
> 
> How does this work? How do you export _mcount if _mcount isn't even
> defined?

_mcount is defined.

This EXPORT_SYMBOL and the _mcount body was inside a
"#ifndef CONFIG_DYNAMIC_FTRACE" section, so if the config has dynamic ftrace
disabled, _mcount is visible.

For the dynamic ftrace case, there is a code snippet in this file:

> ENTRY(ftrace_stub)
> #ifdef CONFIG_DYNAMIC_FTRACE 
>   .global _mcount
>   .set_mcount, ftrace_stub
> #endif
>ret 
> ENDPROC(ftrace_stub)

so the _mcount symbol is visible in the kernel, but not for modules.
As a result, a module build always fails, because _mcount is neither exported,
nor aliased to a defined symbol.

That's the simple purpose of this patch:  we just want to eliminate the errors
during the kernel build process.

> 
> -- Steve

Talking about some bigger issues here, there will be twofold.

1. This patch lacks call-site collecting mechanism.

This feature requires a pattern check in recordmcount.pl.  With this,
section __mcount_loc is properly constructed, and the call-sites will be
registered during the loading stage.

However, the loading will then fail at the first try of make_nop, due to
the instruction check.  This is thus the second issue.


2. The instruction check for kernel texts is not applicable to module texts.

The check expects a call instruction to _mcount, but here it is a call to
the .plt section of the module.  After referencing the implementation of arm64,
I think it would need much more work to have make_nop's and make_call's behavior
right.


Quick summary: This patch ensures that a kernel build will not fail because of
the _mcount-missing problem.  But ftrace cannot trace loading modules for now
due to the stated reasons.

Thanks,
Alan Kao


Re: [PATCH] riscv/ftrace: Fix the problem modules cannot find _mcount

2018-05-08 Thread Alan Kao
On Tue, May 08, 2018 at 09:11:42AM -0400, Steven Rostedt wrote:
> On Tue, 8 May 2018 11:21:57 +0800
> Alan Kao  wrote:
> 
> > Enabling ftrace and module support at the same time fails the kernel
> > build process, because modules cannot find the _mcount symbol.  This
> > patch fixes this issue.
> 
> I think you have a much bigger issue.
>

Yes, we do, but not this one.  Let me state more detail later.
 
> > 
> > Signed-off-by: Alan Kao 
> > Cc: Greentime Hu 
> > Cc: Zong Li 
> > ---
> >  arch/riscv/kernel/mcount.S | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/arch/riscv/kernel/mcount.S b/arch/riscv/kernel/mcount.S
> > index ce9bdc57a2a1..5721624886a1 100644
> > --- a/arch/riscv/kernel/mcount.S
> > +++ b/arch/riscv/kernel/mcount.S
> > @@ -126,5 +126,5 @@ do_trace:
> > RESTORE_ABI_STATE
> > ret
> >  ENDPROC(_mcount)
> > -EXPORT_SYMBOL(_mcount)
> >  #endif
> > +EXPORT_SYMBOL(_mcount)
> 
> How does this work? How do you export _mcount if _mcount isn't even
> defined?

_mcount is defined.

This EXPORT_SYMBOL and the _mcount body was inside a
"#ifndef CONFIG_DYNAMIC_FTRACE" section, so if the config has dynamic ftrace
disabled, _mcount is visible.

For the dynamic ftrace case, there is a code snippet in this file:

> ENTRY(ftrace_stub)
> #ifdef CONFIG_DYNAMIC_FTRACE 
>   .global _mcount
>   .set_mcount, ftrace_stub
> #endif
>ret 
> ENDPROC(ftrace_stub)

so the _mcount symbol is visible in the kernel, but not for modules.
As a result, a module build always fails, because _mcount is neither exported,
nor aliased to a defined symbol.

That's the simple purpose of this patch:  we just want to eliminate the errors
during the kernel build process.

> 
> -- Steve

Talking about some bigger issues here, there will be twofold.

1. This patch lacks call-site collecting mechanism.

This feature requires a pattern check in recordmcount.pl.  With this,
section __mcount_loc is properly constructed, and the call-sites will be
registered during the loading stage.

However, the loading will then fail at the first try of make_nop, due to
the instruction check.  This is thus the second issue.


2. The instruction check for kernel texts is not applicable to module texts.

The check expects a call instruction to _mcount, but here it is a call to
the .plt section of the module.  After referencing the implementation of arm64,
I think it would need much more work to have make_nop's and make_call's behavior
right.


Quick summary: This patch ensures that a kernel build will not fail because of
the _mcount-missing problem.  But ftrace cannot trace loading modules for now
due to the stated reasons.

Thanks,
Alan Kao


  1   2   3   >