Message ID | 20240830061607.1940-3-zhiwei_liu@linux.alibaba.com |
---|---|
State | New |
Headers | show |
Series | tcg/riscv: Add support for vector | expand |
On 8/30/24 16:15, LIU Zhiwei wrote: > +extern unsigned riscv_vlen; Do you really want to store vlen and not vlenb? It seems that would simplify some of your computation in the tcg backend. > @@ -49,6 +50,9 @@ unsigned __attribute__((constructor)) cpuinfo_init(void) > #endif > #if defined(__riscv_arch_test) && defined(__riscv_zicond) > info |= CPUINFO_ZICOND; > +#endif > +#if defined(__riscv_arch_test) && defined(__riscv_zve64x) > + info |= CPUINFO_ZVE64X; > #endif > left &= ~info; > > @@ -64,7 +68,8 @@ unsigned __attribute__((constructor)) cpuinfo_init(void) > && pair.key >= 0) { > info |= pair.value & RISCV_HWPROBE_EXT_ZBA ? CPUINFO_ZBA : 0; > info |= pair.value & RISCV_HWPROBE_EXT_ZBB ? CPUINFO_ZBB : 0; > - left &= ~(CPUINFO_ZBA | CPUINFO_ZBB); > + info |= pair.value & RISCV_HWPROBE_IMA_V ? CPUINFO_ZVE64X : 0; > + left &= ~(CPUINFO_ZBA | CPUINFO_ZBB | CPUINFO_ZVE64X); > #ifdef RISCV_HWPROBE_EXT_ZICOND > info |= pair.value & RISCV_HWPROBE_EXT_ZICOND ? CPUINFO_ZICOND : 0; > left &= ~CPUINFO_ZICOND; > @@ -112,6 +117,23 @@ unsigned __attribute__((constructor)) cpuinfo_init(void) > assert(left == 0); > } > > + if (info & CPUINFO_ZVE64X) { > + /* > + * Get vlen for Vector. > + * VLMAX = LMUL * VLEN / SEW. > + * The "vsetvli rd, x0, e64" means "LMUL = 1, SEW = 64, rd = VLMAX", > + * so "vlen = VLMAX * 64". > + */ > + unsigned long vlmax = 0; > + asm("vsetvli %0, x0, e64" : "=r"(vlmax)); This doesn't compile, surely. s/x0/zero/ is surely the minimum change, but this still won't work unless V is enabled at compile-time. You need to use the .insn form, like we do for the Zba probe above: .insn i 0x57, 7, %0, zero, 3 << 3 I have verified that RISCV_HWPROBE_IMA_V went into the linux kernel at the same time as vector support, so this probing is complete and sufficient. r~
diff --git a/host/include/riscv/host/cpuinfo.h b/host/include/riscv/host/cpuinfo.h index 2b00660e36..48ad6cc3f8 100644 --- a/host/include/riscv/host/cpuinfo.h +++ b/host/include/riscv/host/cpuinfo.h @@ -10,9 +10,11 @@ #define CPUINFO_ZBA (1u << 1) #define CPUINFO_ZBB (1u << 2) #define CPUINFO_ZICOND (1u << 3) +#define CPUINFO_ZVE64X (1u << 4) /* Initialized with a constructor. */ extern unsigned cpuinfo; +extern unsigned riscv_vlen; /* * We cannot rely on constructor ordering, so other constructors must diff --git a/util/cpuinfo-riscv.c b/util/cpuinfo-riscv.c index 497ce12680..780ba59856 100644 --- a/util/cpuinfo-riscv.c +++ b/util/cpuinfo-riscv.c @@ -12,6 +12,7 @@ #endif unsigned cpuinfo; +unsigned riscv_vlen; static volatile sig_atomic_t got_sigill; static void sigill_handler(int signo, siginfo_t *si, void *data) @@ -33,7 +34,7 @@ static void sigill_handler(int signo, siginfo_t *si, void *data) /* Called both as constructor and (possibly) via other constructors. */ unsigned __attribute__((constructor)) cpuinfo_init(void) { - unsigned left = CPUINFO_ZBA | CPUINFO_ZBB | CPUINFO_ZICOND; + unsigned left = CPUINFO_ZBA | CPUINFO_ZBB | CPUINFO_ZICOND | CPUINFO_ZVE64X; unsigned info = cpuinfo; if (info) { @@ -49,6 +50,9 @@ unsigned __attribute__((constructor)) cpuinfo_init(void) #endif #if defined(__riscv_arch_test) && defined(__riscv_zicond) info |= CPUINFO_ZICOND; +#endif +#if defined(__riscv_arch_test) && defined(__riscv_zve64x) + info |= CPUINFO_ZVE64X; #endif left &= ~info; @@ -64,7 +68,8 @@ unsigned __attribute__((constructor)) cpuinfo_init(void) && pair.key >= 0) { info |= pair.value & RISCV_HWPROBE_EXT_ZBA ? CPUINFO_ZBA : 0; info |= pair.value & RISCV_HWPROBE_EXT_ZBB ? CPUINFO_ZBB : 0; - left &= ~(CPUINFO_ZBA | CPUINFO_ZBB); + info |= pair.value & RISCV_HWPROBE_IMA_V ? CPUINFO_ZVE64X : 0; + left &= ~(CPUINFO_ZBA | CPUINFO_ZBB | CPUINFO_ZVE64X); #ifdef RISCV_HWPROBE_EXT_ZICOND info |= pair.value & RISCV_HWPROBE_EXT_ZICOND ? CPUINFO_ZICOND : 0; left &= ~CPUINFO_ZICOND; @@ -112,6 +117,23 @@ unsigned __attribute__((constructor)) cpuinfo_init(void) assert(left == 0); } + if (info & CPUINFO_ZVE64X) { + /* + * Get vlen for Vector. + * VLMAX = LMUL * VLEN / SEW. + * The "vsetvli rd, x0, e64" means "LMUL = 1, SEW = 64, rd = VLMAX", + * so "vlen = VLMAX * 64". + */ + unsigned long vlmax = 0; + asm("vsetvli %0, x0, e64" : "=r"(vlmax)); + if (vlmax) { + riscv_vlen = vlmax * 64; + assert(riscv_vlen >= 64 && !(riscv_vlen & (riscv_vlen - 1))); + } else { + info &= ~CPUINFO_ZVE64X; + } + } + info |= CPUINFO_ALWAYS; cpuinfo = info; return info;