Skip to content

Commit

Permalink
Merge remote-tracking branch 'rth/auxv-2' into staging
Browse files Browse the repository at this point in the history
# By Richard Henderson
# Via Richard Henderson
* rth/auxv-2:
  linux-user: Use qemu_getauxval for AT_EXECFD
  util: Use qemu_getauxval in linux qemu_cache_utils_init
  tcg-s390: Use qemu_getauxval in query_facilities
  tcg-arm: Use qemu_getauxval
  tcg-ppc64: Use qemu_getauxval
  osdep: Create qemu_getauxval and qemu_init_auxval

Message-id: 1385757754-10702-1-git-send-email-rth@twiddle.net
Signed-off-by: Anthony Liguori <aliguori@amazon.com>
  • Loading branch information
Anthony Liguori committed Dec 6, 2013
2 parents a55d121 + 0b959cf commit cdac7a7
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 162 deletions.
73 changes: 73 additions & 0 deletions include/elf.h
Expand Up @@ -411,6 +411,65 @@ typedef struct {
#define R_SPARC_5 44
#define R_SPARC_6 45

/* Bits present in AT_HWCAP for ARM. */

#define HWCAP_ARM_SWP (1 << 0)
#define HWCAP_ARM_HALF (1 << 1)
#define HWCAP_ARM_THUMB (1 << 2)
#define HWCAP_ARM_26BIT (1 << 3)
#define HWCAP_ARM_FAST_MULT (1 << 4)
#define HWCAP_ARM_FPA (1 << 5)
#define HWCAP_ARM_VFP (1 << 6)
#define HWCAP_ARM_EDSP (1 << 7)
#define HWCAP_ARM_JAVA (1 << 8)
#define HWCAP_ARM_IWMMXT (1 << 9)
#define HWCAP_ARM_CRUNCH (1 << 10)
#define HWCAP_ARM_THUMBEE (1 << 11)
#define HWCAP_ARM_NEON (1 << 12)
#define HWCAP_ARM_VFPv3 (1 << 13)
#define HWCAP_ARM_VFPv3D16 (1 << 14) /* also set for VFPv4-D16 */
#define HWCAP_ARM_TLS (1 << 15)
#define HWCAP_ARM_VFPv4 (1 << 16)
#define HWCAP_ARM_IDIVA (1 << 17)
#define HWCAP_ARM_IDIVT (1 << 18)
#define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT)
#define HWCAP_VFPD32 (1 << 19) /* set if VFP has 32 regs */
#define HWCAP_LPAE (1 << 20)

/* Bits present in AT_HWCAP for PowerPC. */

#define PPC_FEATURE_32 0x80000000
#define PPC_FEATURE_64 0x40000000
#define PPC_FEATURE_601_INSTR 0x20000000
#define PPC_FEATURE_HAS_ALTIVEC 0x10000000
#define PPC_FEATURE_HAS_FPU 0x08000000
#define PPC_FEATURE_HAS_MMU 0x04000000
#define PPC_FEATURE_HAS_4xxMAC 0x02000000
#define PPC_FEATURE_UNIFIED_CACHE 0x01000000
#define PPC_FEATURE_HAS_SPE 0x00800000
#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000
#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000
#define PPC_FEATURE_NO_TB 0x00100000
#define PPC_FEATURE_POWER4 0x00080000
#define PPC_FEATURE_POWER5 0x00040000
#define PPC_FEATURE_POWER5_PLUS 0x00020000
#define PPC_FEATURE_CELL 0x00010000
#define PPC_FEATURE_BOOKE 0x00008000
#define PPC_FEATURE_SMT 0x00004000
#define PPC_FEATURE_ICACHE_SNOOP 0x00002000
#define PPC_FEATURE_ARCH_2_05 0x00001000
#define PPC_FEATURE_PA6T 0x00000800
#define PPC_FEATURE_HAS_DFP 0x00000400
#define PPC_FEATURE_POWER6_EXT 0x00000200
#define PPC_FEATURE_ARCH_2_06 0x00000100
#define PPC_FEATURE_HAS_VSX 0x00000080

#define PPC_FEATURE_PSERIES_PERFMON_COMPAT \
0x00000040

#define PPC_FEATURE_TRUE_LE 0x00000002
#define PPC_FEATURE_PPC_LE 0x00000001

/* Bits present in AT_HWCAP, primarily for Sparc32. */

#define HWCAP_SPARC_FLUSH 1 /* CPU supports flush instruction. */
Expand All @@ -420,6 +479,20 @@ typedef struct {
#define HWCAP_SPARC_V9 16
#define HWCAP_SPARC_ULTRA3 32

/* Bits present in AT_HWCAP for s390. */

#define HWCAP_S390_ESAN3 1
#define HWCAP_S390_ZARCH 2
#define HWCAP_S390_STFLE 4
#define HWCAP_S390_MSA 8
#define HWCAP_S390_LDISP 16
#define HWCAP_S390_EIMM 32
#define HWCAP_S390_DFP 64
#define HWCAP_S390_HPAGE 128
#define HWCAP_S390_ETF3EH 256
#define HWCAP_S390_HIGH_GPRS 512
#define HWCAP_S390_TE 1024

/*
* 68k ELF relocation types
*/
Expand Down
4 changes: 2 additions & 2 deletions include/qemu/cache-utils.h
Expand Up @@ -12,7 +12,7 @@ struct qemu_cache_conf {

extern struct qemu_cache_conf qemu_cache_conf;

void qemu_cache_utils_init(char **envp);
void qemu_cache_utils_init(void);

/* mildly adjusted code from tcg-dyngen.c */
static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
Expand All @@ -38,7 +38,7 @@ static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
}

#else
#define qemu_cache_utils_init(envp) do { (void) (envp); } while (0)
#define qemu_cache_utils_init() do { } while (0)
#endif

#endif /* QEMU_CACHE_UTILS_H */
25 changes: 25 additions & 0 deletions include/qemu/osdep.h
Expand Up @@ -215,4 +215,29 @@ bool fips_get_state(void);
*/
char *qemu_get_local_state_pathname(const char *relative_pathname);

/**
* qemu_getauxval:
* @type: the auxiliary vector key to lookup
*
* Search the auxiliary vector for @type, returning the value
* or 0 if @type is not present.
*/
#if defined(CONFIG_GETAUXVAL) || defined(__linux__)
unsigned long qemu_getauxval(unsigned long type);
#else
static inline unsigned long qemu_getauxval(unsigned long type) { return 0; }
#endif

/**
* qemu_init_auxval:
* @envp: the third argument to main
*
* If supported and required, locate the auxiliary vector at program startup.
*/
#if defined(CONFIG_GETAUXVAL) || !defined(__linux__)
static inline void qemu_init_auxval(char **envp) { }
#else
void qemu_init_auxval(char **envp);
#endif

#endif
35 changes: 8 additions & 27 deletions linux-user/main.c
Expand Up @@ -3663,26 +3663,6 @@ static int parse_args(int argc, char **argv)
return optind;
}

static int get_execfd(char **envp)
{
typedef struct {
long a_type;
long a_val;
} auxv_t;
auxv_t *auxv;

while (*envp++ != NULL) {
;
}

for (auxv = (auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) {
if (auxv->a_type == AT_EXECFD) {
return auxv->a_val;
}
}
return -1;
}

int main(int argc, char **argv, char **envp)
{
struct target_pt_regs regs1, *regs = &regs1;
Expand All @@ -3701,7 +3681,8 @@ int main(int argc, char **argv, char **envp)

module_call_init(MODULE_INIT_QOM);

qemu_cache_utils_init(envp);
qemu_init_auxval(envp);
qemu_cache_utils_init();

if ((envlist = envlist_create()) == NULL) {
(void) fprintf(stderr, "Unable to allocate envlist\n");
Expand Down Expand Up @@ -3875,13 +3856,13 @@ int main(int argc, char **argv, char **envp)
env->opaque = ts;
task_settid(ts);

execfd = get_execfd(envp);
if (execfd < 0) {
execfd = qemu_getauxval(AT_EXECFD);
if (execfd == 0) {
execfd = open(filename, O_RDONLY);
}
if (execfd < 0) {
printf("Error while loading %s: %s\n", filename, strerror(-execfd));
_exit(1);
if (execfd < 0) {
printf("Error while loading %s: %s\n", filename, strerror(errno));
_exit(1);
}
}

ret = loader_exec(execfd, filename, target_argv, target_environ, regs,
Expand Down
14 changes: 5 additions & 9 deletions tcg/arm/tcg-target.c
Expand Up @@ -22,6 +22,7 @@
* THE SOFTWARE.
*/

#include "elf.h"
#include "tcg-be-ldst.h"

/* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */
Expand Down Expand Up @@ -58,9 +59,6 @@ static int arm_arch = __ARM_ARCH;
#ifndef use_idiv_instructions
bool use_idiv_instructions;
#endif
#ifdef CONFIG_GETAUXVAL
# include <sys/auxv.h>
#endif

#ifndef NDEBUG
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
Expand Down Expand Up @@ -2036,22 +2034,20 @@ static const TCGTargetOpDef arm_op_defs[] = {

static void tcg_target_init(TCGContext *s)
{
#if defined(CONFIG_GETAUXVAL)
/* Only probe for the platform and capabilities if we havn't already
determined maximum values at compile time. */
# if !defined(use_idiv_instructions)
#ifndef use_idiv_instructions
{
unsigned long hwcap = getauxval(AT_HWCAP);
unsigned long hwcap = qemu_getauxval(AT_HWCAP);
use_idiv_instructions = (hwcap & HWCAP_ARM_IDIVA) != 0;
}
# endif
#endif
if (__ARM_ARCH < 7) {
const char *pl = (const char *)getauxval(AT_PLATFORM);
const char *pl = (const char *)qemu_getauxval(AT_PLATFORM);
if (pl != NULL && pl[0] == 'v' && pl[1] >= '4' && pl[1] <= '9') {
arm_arch = pl[1] - '0';
}
}
#endif /* GETAUXVAL */

tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
tcg_regset_set32(tcg_target_call_clobber_regs, 0,
Expand Down
11 changes: 2 additions & 9 deletions tcg/ppc64/tcg-target.c
Expand Up @@ -45,15 +45,10 @@ static uint8_t *tb_ret_addr;
#define GUEST_BASE 0
#endif

#ifdef CONFIG_GETAUXVAL
#include <sys/auxv.h>
#include "elf.h"
static bool have_isa_2_06;
#define HAVE_ISA_2_06 have_isa_2_06
#define HAVE_ISEL have_isa_2_06
#else
#define HAVE_ISA_2_06 0
#define HAVE_ISEL 0
#endif

#ifdef CONFIG_USE_GUEST_BASE
#define TCG_GUEST_BASE_REG 30
Expand Down Expand Up @@ -2132,12 +2127,10 @@ static const TCGTargetOpDef ppc_op_defs[] = {

static void tcg_target_init(TCGContext *s)
{
#ifdef CONFIG_GETAUXVAL
unsigned long hwcap = getauxval(AT_HWCAP);
unsigned long hwcap = qemu_getauxval(AT_HWCAP);
if (hwcap & PPC_FEATURE_ARCH_2_06) {
have_isa_2_06 = true;
}
#endif

tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
Expand Down
95 changes: 12 additions & 83 deletions tcg/s390/tcg-target.c
Expand Up @@ -31,6 +31,8 @@
#error "unsupported code generation mode"
#endif

#include "elf.h"

/* ??? The translation blocks produced by TCG are generally small enough to
be entirely reachable with a 16-bit displacement. Leaving the option for
a 32-bit displacement here Just In Case. */
Expand Down Expand Up @@ -2233,91 +2235,18 @@ static void sigill_handler(int sig)

static void query_facilities(void)
{
struct sigaction sa_old, sa_new;
register int r0 __asm__("0");
register void *r1 __asm__("1");
int fail;

memset(&sa_new, 0, sizeof(sa_new));
sa_new.sa_handler = sigill_handler;
sigaction(SIGILL, &sa_new, &sa_old);

/* First, try STORE FACILITY LIST EXTENDED. If this is present, then
we need not do any more probing. Unfortunately, this itself is an
extension and the original STORE FACILITY LIST instruction is
kernel-only, storing its results at absolute address 200. */
/* stfle 0(%r1) */
r1 = &facilities;
asm volatile(".word 0xb2b0,0x1000"
: "=r"(r0) : "0"(0), "r"(r1) : "memory", "cc");

if (got_sigill) {
/* STORE FACILITY EXTENDED is not available. Probe for one of each
kind of instruction that we're interested in. */
/* ??? Possibly some of these are in practice never present unless
the store-facility-extended facility is also present. But since
that isn't documented it's just better to probe for each. */

/* Test for z/Architecture. Required even in 31-bit mode. */
got_sigill = 0;
/* agr %r0,%r0 */
asm volatile(".word 0xb908,0x0000" : "=r"(r0) : : "cc");
if (!got_sigill) {
facilities |= FACILITY_ZARCH_ACTIVE;
}

/* Test for long displacement. */
got_sigill = 0;
/* ly %r0,0(%r1) */
r1 = &facilities;
asm volatile(".word 0xe300,0x1000,0x0058"
: "=r"(r0) : "r"(r1) : "cc");
if (!got_sigill) {
facilities |= FACILITY_LONG_DISP;
}

/* Test for extended immediates. */
got_sigill = 0;
/* afi %r0,0 */
asm volatile(".word 0xc209,0x0000,0x0000" : : : "cc");
if (!got_sigill) {
facilities |= FACILITY_EXT_IMM;
}

/* Test for general-instructions-extension. */
got_sigill = 0;
/* msfi %r0,1 */
asm volatile(".word 0xc201,0x0000,0x0001");
if (!got_sigill) {
facilities |= FACILITY_GEN_INST_EXT;
}
}

sigaction(SIGILL, &sa_old, NULL);
unsigned long hwcap = qemu_getauxval(AT_HWCAP);

/* The translator currently uses these extensions unconditionally.
Pruning this back to the base ESA/390 architecture doesn't seem
worthwhile, since even the KVM target requires z/Arch. */
fail = 0;
if ((facilities & FACILITY_ZARCH_ACTIVE) == 0) {
fprintf(stderr, "TCG: z/Arch facility is required.\n");
fprintf(stderr, "TCG: Boot with a 64-bit enabled kernel.\n");
fail = 1;
}
if ((facilities & FACILITY_LONG_DISP) == 0) {
fprintf(stderr, "TCG: long-displacement facility is required.\n");
fail = 1;
}
/* Is STORE FACILITY LIST EXTENDED available? Honestly, I believe this
is present on all 64-bit systems, but let's check for it anyway. */
if (hwcap & HWCAP_S390_STFLE) {
register int r0 __asm__("0");
register void *r1 __asm__("1");

/* So far there's just enough support for 31-bit mode to let the
compile succeed. This is good enough to run QEMU with KVM. */
if (sizeof(void *) != 8) {
fprintf(stderr, "TCG: 31-bit mode is not supported.\n");
fail = 1;
}

if (fail) {
exit(-1);
/* stfle 0(%r1) */
r1 = &facilities;
asm volatile(".word 0xb2b0,0x1000"
: "=r"(r0) : "0"(0), "r"(r1) : "memory", "cc");
}
}

Expand Down
1 change: 1 addition & 0 deletions util/Makefile.objs
Expand Up @@ -12,3 +12,4 @@ util-obj-y += qemu-option.o qemu-progress.o
util-obj-y += hexdump.o
util-obj-y += crc32c.o
util-obj-y += throttle.o
util-obj-y += getauxval.o

0 comments on commit cdac7a7

Please sign in to comment.