Commit 3dca04d6 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'riscv-for-linus-4.20-mw2' of...

Merge tag 'riscv-for-linus-4.20-mw2' of git://git.kernel.org/pub/scm/linux/kernel/git/palmer/riscv-linux

Pull more RISC-V updates from Palmer Dabbelt:
 "This contains the follow-on patches I'd like to target for the 4.20
  merge window. I'm being somewhat conservative here, as while there are
  a few patches on the mailing list that were posted early in the merge
  window I'd like to let those bake for another round -- this was a
  fairly big release as far as RISC-V is concerened, and we need to walk
  before we can run.

  As far as the patches that made it go:

   - A patch to ignore offline CPUs when calculating AT_HWCAP. This
     should fix GDB on the HiFive unleashed, which has an embedded core
     for hart 0 which is exposed to Linux as an offline CPU.

   - A move of EM_RISCV to elf-em.h, which is where it should have been
     to begin with.

   - I've also removed the 64-bit divide routines. I know I'm not really
     playing by my own rules here because I posted the patches this
     morning, but since they shouldn't be in the kernel I think it's
     better to err on the side of going too fast here.

  I don't anticipate any more patch sets for the merge window"

* tag 'riscv-for-linus-4.20-mw2' of git://git.kernel.org/pub/scm/linux/kernel/git/palmer/riscv-linux:
  Move EM_RISCV into elf-em.h
  RISC-V: properly determine hardware caps
  Revert "lib: Add umoddi3 and udivmoddi4 of GCC library routines"
  Revert "RISC-V: Select GENERIC_LIB_UMODDI3 on RV32"
parents 9bb9d4fd ef70696a
...@@ -107,7 +107,6 @@ config ARCH_RV32I ...@@ -107,7 +107,6 @@ config ARCH_RV32I
select GENERIC_LIB_ASHRDI3 select GENERIC_LIB_ASHRDI3
select GENERIC_LIB_LSHRDI3 select GENERIC_LIB_LSHRDI3
select GENERIC_LIB_UCMPDI2 select GENERIC_LIB_UCMPDI2
select GENERIC_LIB_UMODDI3
config ARCH_RV64I config ARCH_RV64I
bool "RV64I" bool "RV64I"
......
...@@ -16,9 +16,6 @@ ...@@ -16,9 +16,6 @@
#include <asm/auxvec.h> #include <asm/auxvec.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
/* TODO: Move definition into include/uapi/linux/elf-em.h */
#define EM_RISCV 0xF3
/* /*
* These are used to set parameters in the core dumps. * These are used to set parameters in the core dumps.
*/ */
......
...@@ -28,7 +28,7 @@ bool has_fpu __read_mostly; ...@@ -28,7 +28,7 @@ bool has_fpu __read_mostly;
void riscv_fill_hwcap(void) void riscv_fill_hwcap(void)
{ {
struct device_node *node; struct device_node *node = NULL;
const char *isa; const char *isa;
size_t i; size_t i;
static unsigned long isa2hwcap[256] = {0}; static unsigned long isa2hwcap[256] = {0};
...@@ -44,9 +44,11 @@ void riscv_fill_hwcap(void) ...@@ -44,9 +44,11 @@ void riscv_fill_hwcap(void)
/* /*
* We don't support running Linux on hertergenous ISA systems. For * We don't support running Linux on hertergenous ISA systems. For
* now, we just check the ISA of the first processor. * now, we just check the ISA of the first "okay" processor.
*/ */
node = of_find_node_by_type(NULL, "cpu"); while ((node = of_find_node_by_type(node, "cpu")))
if (riscv_of_processor_hartid(node) >= 0)
break;
if (!node) { if (!node) {
pr_warning("Unable to find \"cpu\" devicetree entry"); pr_warning("Unable to find \"cpu\" devicetree entry");
return; return;
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#define EM_TILEPRO 188 /* Tilera TILEPro */ #define EM_TILEPRO 188 /* Tilera TILEPro */
#define EM_MICROBLAZE 189 /* Xilinx MicroBlaze */ #define EM_MICROBLAZE 189 /* Xilinx MicroBlaze */
#define EM_TILEGX 191 /* Tilera TILE-Gx */ #define EM_TILEGX 191 /* Tilera TILE-Gx */
#define EM_RISCV 243 /* RISC-V */
#define EM_BPF 247 /* Linux BPF - in-kernel virtual machine */ #define EM_BPF 247 /* Linux BPF - in-kernel virtual machine */
#define EM_FRV 0x5441 /* Fujitsu FR-V */ #define EM_FRV 0x5441 /* Fujitsu FR-V */
......
...@@ -624,6 +624,3 @@ config GENERIC_LIB_CMPDI2 ...@@ -624,6 +624,3 @@ config GENERIC_LIB_CMPDI2
config GENERIC_LIB_UCMPDI2 config GENERIC_LIB_UCMPDI2
bool bool
config GENERIC_LIB_UMODDI3
bool
...@@ -274,4 +274,3 @@ obj-$(CONFIG_GENERIC_LIB_LSHRDI3) += lshrdi3.o ...@@ -274,4 +274,3 @@ obj-$(CONFIG_GENERIC_LIB_LSHRDI3) += lshrdi3.o
obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o
obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o
obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o
obj-$(CONFIG_GENERIC_LIB_UMODDI3) += umoddi3.o udivmoddi4.o
// SPDX-License-Identifier: GPL-2.0
/*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see the file COPYING, or write
* to the Free Software Foundation, Inc.
*/
#include <linux/libgcc.h>
#define count_leading_zeros(COUNT, X) ((COUNT) = __builtin_clz(X))
#define W_TYPE_SIZE 32
#define __ll_B ((unsigned long) 1 << (W_TYPE_SIZE / 2))
#define __ll_lowpart(t) ((unsigned long) (t) & (__ll_B - 1))
#define __ll_highpart(t) ((unsigned long) (t) >> (W_TYPE_SIZE / 2))
/* If we still don't have umul_ppmm, define it using plain C. */
#if !defined(umul_ppmm)
#define umul_ppmm(w1, w0, u, v) \
do { \
unsigned long __x0, __x1, __x2, __x3; \
unsigned short __ul, __vl, __uh, __vh; \
\
__ul = __ll_lowpart(u); \
__uh = __ll_highpart(u); \
__vl = __ll_lowpart(v); \
__vh = __ll_highpart(v); \
\
__x0 = (unsigned long) __ul * __vl; \
__x1 = (unsigned long) __ul * __vh; \
__x2 = (unsigned long) __uh * __vl; \
__x3 = (unsigned long) __uh * __vh; \
\
__x1 += __ll_highpart(__x0); \
__x1 += __x2; \
if (__x1 < __x2) \
__x3 += __ll_B; \
\
(w1) = __x3 + __ll_highpart(__x1); \
(w0) = __ll_lowpart(__x1) * __ll_B + __ll_lowpart(__x0);\
} while (0)
#endif
#if !defined(sub_ddmmss)
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
do { \
unsigned long __x; \
__x = (al) - (bl); \
(sh) = (ah) - (bh) - (__x > (al)); \
(sl) = __x; \
} while (0)
#endif
/* Define this unconditionally, so it can be used for debugging. */
#define __udiv_qrnnd_c(q, r, n1, n0, d) \
do { \
unsigned long __d1, __d0, __q1, __q0; \
unsigned long __r1, __r0, __m; \
__d1 = __ll_highpart(d); \
__d0 = __ll_lowpart(d); \
\
__r1 = (n1) % __d1; \
__q1 = (n1) / __d1; \
__m = (unsigned long) __q1 * __d0; \
__r1 = __r1 * __ll_B | __ll_highpart(n0); \
if (__r1 < __m) { \
__q1--, __r1 += (d); \
if (__r1 >= (d)) \
if (__r1 < __m) \
__q1--, __r1 += (d); \
} \
__r1 -= __m; \
\
__r0 = __r1 % __d1; \
__q0 = __r1 / __d1; \
__m = (unsigned long) __q0 * __d0; \
__r0 = __r0 * __ll_B | __ll_lowpart(n0); \
if (__r0 < __m) { \
__q0--, __r0 += (d); \
if (__r0 >= (d)) \
if (__r0 < __m) \
__q0--, __r0 += (d); \
} \
__r0 -= __m; \
\
(q) = (unsigned long) __q1 * __ll_B | __q0; \
(r) = __r0; \
} while (0)
/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */
#if !defined(udiv_qrnnd)
#define UDIV_NEEDS_NORMALIZATION 1
#define udiv_qrnnd __udiv_qrnnd_c
#endif
unsigned long long __udivmoddi4(unsigned long long u, unsigned long long v,
unsigned long long *rp)
{
const DWunion nn = {.ll = u };
const DWunion dd = {.ll = v };
DWunion rr, ww;
unsigned long d0, d1, n0, n1, n2;
unsigned long q0 = 0, q1 = 0;
unsigned long b, bm;
d0 = dd.s.low;
d1 = dd.s.high;
n0 = nn.s.low;
n1 = nn.s.high;
#if !UDIV_NEEDS_NORMALIZATION
if (d1 == 0) {
if (d0 > n1) {
/* 0q = nn / 0D */
udiv_qrnnd(q0, n0, n1, n0, d0);
q1 = 0;
/* Remainder in n0. */
} else {
/* qq = NN / 0d */
if (d0 == 0)
/* Divide intentionally by zero. */
d0 = 1 / d0;
udiv_qrnnd(q1, n1, 0, n1, d0);
udiv_qrnnd(q0, n0, n1, n0, d0);
/* Remainder in n0. */
}
if (rp != 0) {
rr.s.low = n0;
rr.s.high = 0;
*rp = rr.ll;
}
#else /* UDIV_NEEDS_NORMALIZATION */
if (d1 == 0) {
if (d0 > n1) {
/* 0q = nn / 0D */
count_leading_zeros(bm, d0);
if (bm != 0) {
/*
* Normalize, i.e. make the most significant bit
* of the denominator set.
*/
d0 = d0 << bm;
n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
n0 = n0 << bm;
}
udiv_qrnnd(q0, n0, n1, n0, d0);
q1 = 0;
/* Remainder in n0 >> bm. */
} else {
/* qq = NN / 0d */
if (d0 == 0)
/* Divide intentionally by zero. */
d0 = 1 / d0;
count_leading_zeros(bm, d0);
if (bm == 0) {
/*
* From (n1 >= d0) /\ (the most significant bit
* of d0 is set), conclude (the most significant
* bit of n1 is set) /\ (theleading quotient
* digit q1 = 1).
*
* This special case is necessary, not an
* optimization. (Shifts counts of W_TYPE_SIZE
* are undefined.)
*/
n1 -= d0;
q1 = 1;
} else {
/* Normalize. */
b = W_TYPE_SIZE - bm;
d0 = d0 << bm;
n2 = n1 >> b;
n1 = (n1 << bm) | (n0 >> b);
n0 = n0 << bm;
udiv_qrnnd(q1, n1, n2, n1, d0);
}
/* n1 != d0... */
udiv_qrnnd(q0, n0, n1, n0, d0);
/* Remainder in n0 >> bm. */
}
if (rp != 0) {
rr.s.low = n0 >> bm;
rr.s.high = 0;
*rp = rr.ll;
}
#endif /* UDIV_NEEDS_NORMALIZATION */
} else {
if (d1 > n1) {
/* 00 = nn / DD */
q0 = 0;
q1 = 0;
/* Remainder in n1n0. */
if (rp != 0) {
rr.s.low = n0;
rr.s.high = n1;
*rp = rr.ll;
}
} else {
/* 0q = NN / dd */
count_leading_zeros(bm, d1);
if (bm == 0) {
/*
* From (n1 >= d1) /\ (the most significant bit
* of d1 is set), conclude (the most significant
* bit of n1 is set) /\ (the quotient digit q0 =
* 0 or 1).
*
* This special case is necessary, not an
* optimization.
*/
/*
* The condition on the next line takes
* advantage of that n1 >= d1 (true due to
* program flow).
*/
if (n1 > d1 || n0 >= d0) {
q0 = 1;
sub_ddmmss(n1, n0, n1, n0, d1, d0);
} else {
q0 = 0;
}
q1 = 0;
if (rp != 0) {
rr.s.low = n0;
rr.s.high = n1;
*rp = rr.ll;
}
} else {
unsigned long m1, m0;
/* Normalize. */
b = W_TYPE_SIZE - bm;
d1 = (d1 << bm) | (d0 >> b);
d0 = d0 << bm;
n2 = n1 >> b;
n1 = (n1 << bm) | (n0 >> b);
n0 = n0 << bm;
udiv_qrnnd(q0, n1, n2, n1, d1);
umul_ppmm(m1, m0, q0, d0);
if (m1 > n1 || (m1 == n1 && m0 > n0)) {
q0--;
sub_ddmmss(m1, m0, m1, m0, d1, d0);
}
q1 = 0;
/* Remainder in (n1n0 - m1m0) >> bm. */
if (rp != 0) {
sub_ddmmss(n1, n0, n1, n0, m1, m0);
rr.s.low = (n1 << b) | (n0 >> bm);
rr.s.high = n1 >> bm;
*rp = rr.ll;
}
}
}
}
ww.s.low = q0;
ww.s.high = q1;
return ww.ll;
}
// SPDX-License-Identifier: GPL-2.0
/*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see the file COPYING, or write
* to the Free Software Foundation, Inc.
*/
#include <linux/module.h>
#include <linux/libgcc.h>
extern unsigned long long __udivmoddi4(unsigned long long u,
unsigned long long v,
unsigned long long *rp);
unsigned long long __umoddi3(unsigned long long u, unsigned long long v)
{
unsigned long long w;
(void)__udivmoddi4(u, v, &w);
return w;
}
EXPORT_SYMBOL(__umoddi3);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment