1/*
2 *  Copyright (c) 2017 The WebM project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include <fcntl.h>
12#include <unistd.h>
13#include <stdint.h>
14#include <asm/cputable.h>
15#include <linux/auxvec.h>
16
17#include "./vpx_config.h"
18#include "vpx_ports/ppc.h"
19
20#if CONFIG_RUNTIME_CPU_DETECT
21static int cpu_env_flags(int *flags) {
22  char *env;
23  env = getenv("VPX_SIMD_CAPS");
24  if (env && *env) {
25    *flags = (int)strtol(env, NULL, 0);
26    return 0;
27  }
28  *flags = 0;
29  return -1;
30}
31
32static int cpu_env_mask(void) {
33  char *env;
34  env = getenv("VPX_SIMD_CAPS_MASK");
35  return env && *env ? (int)strtol(env, NULL, 0) : ~0;
36}
37
38int ppc_simd_caps(void) {
39  int flags;
40  int mask;
41  int fd;
42  ssize_t count;
43  unsigned int i;
44  uint64_t buf[64];
45
46  // If VPX_SIMD_CAPS is set then allow only those capabilities.
47  if (!cpu_env_flags(&flags)) {
48    return flags;
49  }
50
51  mask = cpu_env_mask();
52
53  fd = open("/proc/self/auxv", O_RDONLY);
54  if (fd < 0) {
55    return 0;
56  }
57
58  while ((count = read(fd, buf, sizeof(buf))) > 0) {
59    for (i = 0; i < (count / sizeof(*buf)); i += 2) {
60      if (buf[i] == AT_HWCAP) {
61#if HAVE_VSX
62        if (buf[i + 1] & PPC_FEATURE_HAS_VSX) {
63          flags |= HAS_VSX;
64        }
65#endif  // HAVE_VSX
66        goto out_close;
67      } else if (buf[i] == AT_NULL) {
68        goto out_close;
69      }
70    }
71  }
72out_close:
73  close(fd);
74  return flags & mask;
75}
76#else
77// If there is no RTCD the function pointers are not used and can not be
78// changed.
79int ppc_simd_caps(void) { return 0; }
80#endif  // CONFIG_RUNTIME_CPU_DETECT
81