1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
#ifndef ARCH_PPC_H
#define ARCH_PPC_H
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#define FIO_ARCH (arch_ppc)
#define nop do { } while (0)
#ifdef __powerpc64__
#define read_barrier() __asm__ __volatile__ ("lwsync" : : : "memory")
#else
#define read_barrier() __asm__ __volatile__ ("sync" : : : "memory")
#endif
#define write_barrier() __asm__ __volatile__ ("sync" : : : "memory")
#ifdef __powerpc64__
#define PPC_CNTLZL "cntlzd"
#else
#define PPC_CNTLZL "cntlzw"
#endif
static inline int __ilog2(unsigned long bitmask)
{
int lz;
asm (PPC_CNTLZL " %0,%1" : "=r" (lz) : "r" (bitmask));
return BITS_PER_LONG - 1 - lz;
}
static inline int arch_ffz(unsigned long bitmask)
{
if ((bitmask = ~bitmask) == 0)
return BITS_PER_LONG;
return __ilog2(bitmask & -bitmask);
}
static inline unsigned int mfspr(unsigned int reg)
{
unsigned int val;
asm volatile("mfspr %0,%1": "=r" (val) : "K" (reg));
return val;
}
#define SPRN_TBRL 0x10C /* Time Base Register Lower */
#define SPRN_TBRU 0x10D /* Time Base Register Upper */
#define SPRN_ATBL 0x20E /* Alternate Time Base Lower */
#define SPRN_ATBU 0x20F /* Alternate Time Base Upper */
#ifdef __powerpc64__
static inline unsigned long long get_cpu_clock(void)
{
unsigned long long rval;
asm volatile(
"90: mfspr %0, %1;\n"
" cmpwi %0,0;\n"
" beq- 90b;\n"
: "=r" (rval)
: "i" (SPRN_TBRL)
: "cr0");
return rval;
}
#else
static inline unsigned long long get_cpu_clock(void)
{
unsigned int tbl, tbu0, tbu1;
unsigned long long ret;
do {
if (arch_flags & ARCH_FLAG_1) {
tbu0 = mfspr(SPRN_ATBU);
tbl = mfspr(SPRN_ATBL);
tbu1 = mfspr(SPRN_ATBU);
} else {
tbu0 = mfspr(SPRN_TBRU);
tbl = mfspr(SPRN_TBRL);
tbu1 = mfspr(SPRN_TBRU);
}
} while (tbu0 != tbu1);
ret = (((unsigned long long)tbu0) << 32) | tbl;
return ret;
}
#endif
#if 0
static void atb_child(void)
{
arch_flags |= ARCH_FLAG_1;
get_cpu_clock();
_exit(0);
}
static void atb_clocktest(void)
{
pid_t pid;
pid = fork();
if (!pid)
atb_child();
else if (pid != -1) {
int status;
pid = wait(&status);
if (pid == -1 || !WIFEXITED(status))
arch_flags &= ~ARCH_FLAG_1;
else
arch_flags |= ARCH_FLAG_1;
}
}
#endif
#define ARCH_HAVE_INIT
extern bool tsc_reliable;
static inline int arch_init(char *envp[])
{
#if 0
tsc_reliable = true;
atb_clocktest();
#endif
return 0;
}
#define ARCH_HAVE_FFZ
/*
* We don't have it on all platforms, lets comment this out until we
* can handle it more intelligently.
*
* #define ARCH_HAVE_CPU_CLOCK
*/
/*
* Let's have it defined for ppc64
*/
#ifdef __powerpc64__
#define ARCH_HAVE_CPU_CLOCK
#endif
#endif
|