Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1efea40d authored by Chris Metcalf's avatar Chris Metcalf
Browse files

arch/tile: support building big-endian kernel



The toolchain supports big-endian mode now, so add support for building
the kernel to run big-endian as well.

Signed-off-by: default avatarChris Metcalf <cmetcalf@tilera.com>
parent 73636b1a
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
/*
 * Copyright 2011 Tilera Corporation. All Rights Reserved.
 *
 *   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, version 2.
 *
 *   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, GOOD TITLE or
 *   NON INFRINGEMENT.  See the GNU General Public License for
 *   more details.
 */

#if defined (__BIG_ENDIAN__)
#include <linux/byteorder/big_endian.h>
#elif defined (__LITTLE_ENDIAN__)
#include <linux/byteorder/little_endian.h>
#else
#error "__BIG_ENDIAN__ or __LITTLE_ENDIAN__ must be defined."
#endif
+5 −0
Original line number Diff line number Diff line
@@ -44,7 +44,11 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
#else
#define ELF_CLASS	ELFCLASS32
#endif
#ifdef __BIG_ENDIAN__
#define ELF_DATA	ELFDATA2MSB
#else
#define ELF_DATA	ELFDATA2LSB
#endif

/*
 * There seems to be a bug in how compat_binfmt_elf.c works: it
@@ -59,6 +63,7 @@ enum { ELF_ARCH = CHIP_ELF_TYPE() };
 */
#define elf_check_arch(x)  \
	((x)->e_ident[EI_CLASS] == ELF_CLASS && \
	 (x)->e_ident[EI_DATA] == ELF_DATA && \
	 (x)->e_machine == CHIP_ELF_TYPE())

/* The module loader only handles a few relocation types. */
+16 −0
Original line number Diff line number Diff line
@@ -494,11 +494,16 @@ int hv_confstr(HV_ConfstrQuery query, HV_VirtAddr buf, int len);
/** Tile coordinate */
typedef struct
{
#ifndef __BIG_ENDIAN__
  /** X coordinate, relative to supervisor's top-left coordinate */
  int x;

  /** Y coordinate, relative to supervisor's top-left coordinate */
  int y;
#else
  int y;
  int x;
#endif
} HV_Coord;


@@ -986,8 +991,13 @@ HV_VirtAddrRange hv_inquire_virtual(int idx);
/** A range of ASID values. */
typedef struct
{
#ifndef __BIG_ENDIAN__
  HV_ASID start;        /**< First ASID in the range. */
  unsigned int size;    /**< Number of ASIDs. Zero for an invalid range. */
#else
  unsigned int size;    /**< Number of ASIDs. Zero for an invalid range. */
  HV_ASID start;        /**< First ASID in the range. */
#endif
} HV_ASIDRange;

/** Returns information about a range of ASIDs.
@@ -1308,6 +1318,7 @@ typedef enum
/** Message recipient. */
typedef struct
{
#ifndef __BIG_ENDIAN__
  /** X coordinate, relative to supervisor's top-left coordinate */
  unsigned int x:11;

@@ -1316,6 +1327,11 @@ typedef struct

  /** Status of this recipient */
  HV_Recip_State state:10;
#else //__BIG_ENDIAN__
  HV_Recip_State state:10;
  unsigned int y:11;
  unsigned int x:11;
#endif
} HV_Recipient;

/** Send a message to a set of recipients.
+11 −1
Original line number Diff line number Diff line
@@ -159,7 +159,17 @@ int apply_relocate_add(Elf_Shdr *sechdrs,

		switch (ELF_R_TYPE(rel[i].r_info)) {

#define MUNGE(func) (*location = ((*location & ~func(-1)) | func(value)))
#ifdef __LITTLE_ENDIAN
# define MUNGE(func) \
	(*location = ((*location & ~func(-1)) | func(value)))
#else
/*
 * Instructions are always little-endian, so when we read them as data,
 * we have to swap them around before and after modifying them.
 */
# define MUNGE(func) \
	(*location = swab64((swab64(*location) & ~func(-1)) | func(value)))
#endif

#ifndef __tilegx__
		case R_TILE_32:
+12 −4
Original line number Diff line number Diff line
@@ -172,9 +172,6 @@ static tile_bundle_bits rewrite_load_store_unaligned(
		return (tilepro_bundle_bits) 0;
	}

#ifndef __LITTLE_ENDIAN
# error We assume little-endian representation with copy_xx_user size 2 here
#endif
	/* Handle unaligned load/store */
	if (mem_op == MEMOP_LOAD || mem_op == MEMOP_LOAD_POSTINCR) {
		unsigned short val_16;
@@ -195,8 +192,19 @@ static tile_bundle_bits rewrite_load_store_unaligned(
			state->update = 1;
		}
	} else {
		unsigned short val_16;
		val = (val_reg == TREG_ZERO) ? 0 : regs->regs[val_reg];
		err = copy_to_user(addr, &val, size);
		switch (size) {
		case 2:
			val_16 = val;
			err = copy_to_user(addr, &val_16, sizeof(val_16));
			break;
		case 4:
			err = copy_to_user(addr, &val, sizeof(val));
			break;
		default:
			BUG();
		}
	}

	if (err) {
Loading