linux-mips
[Top] [All Lists]

Re: [PATCH 05/36] Add Cavium OCTEON processor support files to and arch/

To: David Daney <ddaney@caviumnetworks.com>
Subject: Re: [PATCH 05/36] Add Cavium OCTEON processor support files to and arch/mips/cavium-octeon/executive
From: Christoph Hellwig <hch@lst.de>
Date: Wed, 29 Oct 2008 19:45:18 +0100
Cc: linux-mips@linux-mips.org, Tomaso Paoletti <tpaoletti@caviumnetworks.com>
In-reply-to: <1225152181-3221-5-git-send-email-ddaney@caviumnetworks.com>
Original-recipient: rfc822;linux-mips@linux-mips.org
References: <490655B6.4030406@caviumnetworks.com> <1225152181-3221-1-git-send-email-ddaney@caviumnetworks.com> <1225152181-3221-2-git-send-email-ddaney@caviumnetworks.com> <1225152181-3221-3-git-send-email-ddaney@caviumnetworks.com> <1225152181-3221-4-git-send-email-ddaney@caviumnetworks.com> <1225152181-3221-5-git-send-email-ddaney@caviumnetworks.com>
Sender: linux-mips-bounce@linux-mips.org
User-agent: Mutt/1.3.28i
So what is all this crappy code actually supposed to do?

A little explanation would help, or in this case I suspect even an
explanation might not help anyore.

On Mon, Oct 27, 2008 at 05:02:37PM -0700, David Daney wrote:
> Signed-off-by: Tomaso Paoletti <tpaoletti@caviumnetworks.com>
> Signed-off-by: David Daney <ddaney@caviumnetworks.com>
> ---
>  arch/mips/cavium-octeon/executive/Makefile         |   26 +
>  arch/mips/cavium-octeon/executive/cvmx-asm.h       |  427 ++++++++++
>  arch/mips/cavium-octeon/executive/cvmx-bootinfo.h  |  238 ++++++
>  arch/mips/cavium-octeon/executive/cvmx-bootmem.c   |  897 
> ++++++++++++++++++++
>  arch/mips/cavium-octeon/executive/cvmx-bootmem.h   |  403 +++++++++
>  arch/mips/cavium-octeon/executive/cvmx-interrupt.h |  255 ++++++
>  arch/mips/cavium-octeon/executive/cvmx-l2c.c       |  711 ++++++++++++++++
>  arch/mips/cavium-octeon/executive/cvmx-l2c.h       |  328 +++++++
>  .../executive/cvmx-linux-kernel-exports.c          |   30 +
>  arch/mips/cavium-octeon/executive/cvmx-packet.h    |   64 ++
>  arch/mips/cavium-octeon/executive/cvmx-platform.h  |   56 ++
>  arch/mips/cavium-octeon/executive/cvmx-spinlock.h  |  376 ++++++++
>  arch/mips/cavium-octeon/executive/cvmx-sysinfo.c   |  113 +++
>  arch/mips/cavium-octeon/executive/cvmx-sysinfo.h   |  144 ++++
>  arch/mips/cavium-octeon/executive/cvmx-warn.c      |   44 +
>  arch/mips/cavium-octeon/executive/cvmx-warn.h      |   46 +
>  arch/mips/cavium-octeon/executive/cvmx.h           |  772 +++++++++++++++++
>  arch/mips/cavium-octeon/executive/octeon-feature.h |  120 +++
>  arch/mips/cavium-octeon/executive/octeon-model.c   |  328 +++++++
>  arch/mips/cavium-octeon/executive/octeon-model.h   |  225 +++++
>  20 files changed, 5603 insertions(+), 0 deletions(-)
>  create mode 100644 arch/mips/cavium-octeon/executive/Makefile
>  create mode 100644 arch/mips/cavium-octeon/executive/cvmx-asm.h
>  create mode 100644 arch/mips/cavium-octeon/executive/cvmx-bootinfo.h
>  create mode 100644 arch/mips/cavium-octeon/executive/cvmx-bootmem.c
>  create mode 100644 arch/mips/cavium-octeon/executive/cvmx-bootmem.h
>  create mode 100644 arch/mips/cavium-octeon/executive/cvmx-interrupt.h
>  create mode 100644 arch/mips/cavium-octeon/executive/cvmx-l2c.c
>  create mode 100644 arch/mips/cavium-octeon/executive/cvmx-l2c.h
>  create mode 100644 
> arch/mips/cavium-octeon/executive/cvmx-linux-kernel-exports.c
>  create mode 100644 arch/mips/cavium-octeon/executive/cvmx-packet.h
>  create mode 100644 arch/mips/cavium-octeon/executive/cvmx-platform.h
>  create mode 100644 arch/mips/cavium-octeon/executive/cvmx-spinlock.h
>  create mode 100644 arch/mips/cavium-octeon/executive/cvmx-sysinfo.c
>  create mode 100644 arch/mips/cavium-octeon/executive/cvmx-sysinfo.h
>  create mode 100644 arch/mips/cavium-octeon/executive/cvmx-warn.c
>  create mode 100644 arch/mips/cavium-octeon/executive/cvmx-warn.h
>  create mode 100644 arch/mips/cavium-octeon/executive/cvmx.h
>  create mode 100644 arch/mips/cavium-octeon/executive/octeon-feature.h
>  create mode 100644 arch/mips/cavium-octeon/executive/octeon-model.c
>  create mode 100644 arch/mips/cavium-octeon/executive/octeon-model.h
> 
> diff --git a/arch/mips/cavium-octeon/executive/Makefile 
> b/arch/mips/cavium-octeon/executive/Makefile
> new file mode 100644
> index 0000000..cb51c58
> --- /dev/null
> +++ b/arch/mips/cavium-octeon/executive/Makefile
> @@ -0,0 +1,26 @@
> +#
> +# Makefile for the Cavium Octeon specific kernel interface routines
> +# under Linux.
> +#
> +# This file is subject to the terms and conditions of the GNU General Public
> +# License.  See the file "COPYING" in the main directory of this archive
> +# for more details.
> +#
> +# Copyright (C) 2005-2007 Cavium Networks
> +#
> +
> +
> +source:=$(srctree)/$(src)
> +EXTRA_CFLAGS += -I$(source) -I$(source)/config
> +
> +executive-files := cvmx-bootmem.o
> +executive-files += cvmx-l2c.o
> +executive-files += cvmx-sysinfo.o
> +executive-files += cvmx-warn.o
> +executive-files += octeon-model.o
> +executive-files += cvmx-linux-kernel-exports.o
> +obj-y := $(executive-files)
> +
> +executive-obj-files := $(executive-files:%=$(obj)/%)
> +executive-src-files := $(executive-obj-files:%.o=%.c)
> +
> diff --git a/arch/mips/cavium-octeon/executive/cvmx-asm.h 
> b/arch/mips/cavium-octeon/executive/cvmx-asm.h
> new file mode 100644
> index 0000000..8516456
> --- /dev/null
> +++ b/arch/mips/cavium-octeon/executive/cvmx-asm.h
> @@ -0,0 +1,427 @@
> +/***********************license start***************
> + * Author: Cavium Networks
> + *
> + * Contact: support@caviumnetworks.com
> + * This file is part of the OCTEON SDK
> + *
> + * Copyright (c) 2003-2008 Cavium Networks
> + *
> + * This file is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, Version 2, as 
> published by
> + * the Free Software Foundation.
> + *
> + * This file is distributed in the hope that it will be useful,
> + * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 
> NONINFRINGEMENT.
> + * See the GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this file; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + * or visit http://www.gnu.org/licenses/.
> + *
> + * This file may also be available under a different license from Cavium.
> + * Contact Cavium Networks for more information
> + ***********************license end**************************************/
> +
> +/**
> + * @file
> + *
> + * This is file defines ASM primitives for the executive.
> +
> + *
> + *
> + */
> +#ifndef __CVMX_ASM_H__
> +#define __CVMX_ASM_H__
> +
> +#include "octeon-model.h"
> +
> +/* other useful stuff */
> +#define CVMX_BREAK asm volatile ("break")
> +#define CVMX_SYNC asm volatile ("sync" : : :"memory")
> +/* String version of SYNCW macro for using in inline asm constructs */
> +#define CVMX_SYNCW_STR "syncw\nsyncw\n"
> +#ifdef __OCTEON__
> +#define CVMX_SYNCIO asm volatile ("nop")     /* Deprecated, will be removed 
> in future release */
> +#define CVMX_SYNCIOBDMA asm volatile ("synciobdma" : : :"memory")
> +#define CVMX_SYNCIOALL asm volatile ("nop")  /* Deprecated, will be removed 
> in future release */
> +     /* We actually use two syncw instructions in a row when we need a write
> +        memory barrier. This is because the CN3XXX series of Octeons have
> +        errata Core-401. This can cause a single syncw to not enforce
> +        ordering under very rare conditions. Even if it is rare, better safe
> +        than sorry */
> +#define CVMX_SYNCW asm volatile ("syncw\nsyncw\n" : : :"memory")
> +     /* Define new sync instructions to be normal SYNC instructions for
> +        operating systems that use threads */
> +#define CVMX_SYNCWS CVMX_SYNCW
> +#define CVMX_SYNCS  CVMX_SYNC
> +#define CVMX_SYNCWS_STR CVMX_SYNCW_STR
> +#else
> +     /* Not using a Cavium compiler, always use the slower sync so the 
> assembler stays happy */
> +#define CVMX_SYNCIO asm volatile ("nop")     /* Deprecated, will be removed 
> in future release */
> +#define CVMX_SYNCIOBDMA asm volatile ("sync" : : :"memory")
> +#define CVMX_SYNCIOALL asm volatile ("nop")  /* Deprecated, will be removed 
> in future release */
> +#define CVMX_SYNCW asm volatile ("sync" : : :"memory")
> +#define CVMX_SYNCWS CVMX_SYNCW
> +#define CVMX_SYNCS  CVMX_SYNC
> +#define CVMX_SYNCWS_STR CVMX_SYNCW_STR
> +#endif
> +#define CVMX_SYNCI(address, offset) asm volatile ("synci " 
> CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
> +#define CVMX_PREFETCH0(address) CVMX_PREFETCH(address, 0)
> +#define CVMX_PREFETCH128(address) CVMX_PREFETCH(address, 128)
> +/* a normal prefetch */
> +#define CVMX_PREFETCH(address, offset) CVMX_PREFETCH_PREF0(address, offset)
> +/* normal prefetches that use the pref instruction */
> +#define CVMX_PREFETCH_PREF0(address, offset) asm volatile ("pref 0, " 
> CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
> +#define CVMX_PREFETCH_PREF1(address, offset) asm volatile ("pref 1, " 
> CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
> +#define CVMX_PREFETCH_PREF6(address, offset) asm volatile ("pref 6, " 
> CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
> +#define CVMX_PREFETCH_PREF7(address, offset) asm volatile ("pref 7, " 
> CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
> +/* prefetch into L1, do not put the block in the L2 */
> +#define CVMX_PREFETCH_NOTL2(address, offset) asm volatile ("pref 4, " 
> CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
> +#define CVMX_PREFETCH_NOTL22(address, offset) asm volatile ("pref 5, " 
> CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
> +/* prefetch into L2, do not put the block in the L1 */
> +#define CVMX_PREFETCH_L2(address, offset) asm volatile ("pref 28, " 
> CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
> +/* CVMX_PREPARE_FOR_STORE makes each byte of the block unpredictable 
> (actually old value or zero) until */
> +/* that byte is stored to (by this or another processor. Note that the value 
> of each byte is not only */
> +/* unpredictable, but may also change again - up until the point when one of 
> the cores stores to the */
> +/* byte. */
> +#define CVMX_PREPARE_FOR_STORE(address, offset) asm volatile ("pref 30, " 
> CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
> +/* This is a command headed to the L2 controller to tell it to clear its 
> dirty bit for a */
> +/* block. Basically, SW is telling HW that the current version of the block 
> will not be */
> +/* used. */
> +#define CVMX_DONT_WRITE_BACK(address, offset) asm volatile ("pref 29, " 
> CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
> +
> +#define CVMX_ICACHE_INVALIDATE  { CVMX_SYNC; asm volatile ("synci 0($0)" : : 
> ); }    /* flush stores, invalidate entire icache */
> +#define CVMX_ICACHE_INVALIDATE2 { CVMX_SYNC; asm volatile ("cache 0, 0($0)" 
> : : ); } /* flush stores, invalidate entire icache */
> +#define CVMX_DCACHE_INVALIDATE  { CVMX_SYNC; asm volatile ("cache 9, 0($0)" 
> : : ); } /* complete prefetches, invalidate entire dcache */
> +
> +/* new instruction to make RC4 run faster */
> +#define CVMX_BADDU(result, input1, input2) asm ("baddu %[rd],%[rs],%[rt]" : 
> [rd] "=d" (result) : [rs] "d" (input1) , [rt] "d" (input2))
> +
> +/* misc v2 stuff */
> +#define CVMX_ROTR(result, input1, shiftconst) asm ("rotr %[rd],%[rs]," 
> CVMX_TMP_STR(shiftconst) : [rd] "=d" (result) : [rs] "d" (input1))
> +#define CVMX_ROTRV(result, input1, input2) asm ("rotrv %[rd],%[rt],%[rs]" : 
> [rd] "=d" (result) : [rt] "d" (input1) , [rs] "d" (input2))
> +#define CVMX_DROTR(result, input1, shiftconst) asm ("drotr %[rd],%[rs]," 
> CVMX_TMP_STR(shiftconst) : [rd] "=d" (result) : [rs] "d" (input1))
> +#define CVMX_DROTRV(result, input1, input2) asm ("drotrv %[rd],%[rt],%[rs]" 
> : [rd] "=d" (result) : [rt] "d" (input1) , [rs] "d" (input2))
> +#define CVMX_SEB(result, input1) asm ("seb %[rd],%[rt]" : [rd] "=d" (result) 
> : [rt] "d" (input1))
> +#define CVMX_SEH(result, input1) asm ("seh %[rd],%[rt]" : [rd] "=d" (result) 
> : [rt] "d" (input1))
> +#define CVMX_DSBH(result, input1) asm ("dsbh %[rd],%[rt]" : [rd] "=d" 
> (result) : [rt] "d" (input1))
> +#define CVMX_DSHD(result, input1) asm ("dshd %[rd],%[rt]" : [rd] "=d" 
> (result) : [rt] "d" (input1))
> +#define CVMX_WSBH(result, input1) asm ("wsbh %[rd],%[rt]" : [rd] "=d" 
> (result) : [rt] "d" (input1))
> +
> +/* Endian swap */
> +#define CVMX_ES64(result, input) \
> +        do {\
> +        CVMX_DSBH(result, input); \
> +        CVMX_DSHD(result, result); \
> +        } while (0)
> +#define CVMX_ES32(result, input) \
> +        do {\
> +        CVMX_WSBH(result, input); \
> +        CVMX_ROTR(result, result, 16); \
> +        } while (0)
> +
> +/* extract and insert - NOTE that pos and len variables must be constants! */
> +/* the P variants take len rather than lenm1 */
> +/* the M1 variants take lenm1 rather than len */
> +#define CVMX_EXTS(result,input,pos,lenm1) asm ("exts %[rt],%[rs]," 
> CVMX_TMP_STR(pos) "," CVMX_TMP_STR(lenm1) : [rt] "=d" (result) : [rs] "d" 
> (input))
> +#define CVMX_EXTSP(result,input,pos,len) CVMX_EXTS(result,input,pos,(len)-1)
> +
> +#define CVMX_DEXT(result,input,pos,len) asm ("dext %[rt],%[rs]," 
> CVMX_TMP_STR(pos) "," CVMX_TMP_STR(len) : [rt] "=d" (result) : [rs] "d" 
> (input))
> +#define CVMX_DEXTM1(result,input,pos,lenm1) 
> CVMX_DEXT(result,input,pos,(lenm1)+1)
> +
> +#define CVMX_EXT(result,input,pos,len) asm ("ext %[rt],%[rs]," 
> CVMX_TMP_STR(pos) "," CVMX_TMP_STR(len) : [rt] "=d" (result) : [rs] "d" 
> (input))
> +#define CVMX_EXTM1(result,input,pos,lenm1) 
> CVMX_EXT(result,input,pos,(lenm1)+1)
> +
> +/* removed */
> +/* #define CVMX_EXTU(result,input,pos,lenm1) asm ("extu %[rt],%[rs]," 
> CVMX_TMP_STR(pos) "," CVMX_TMP_STR(lenm1) : [rt] "=d" (result) : [rs] "d" 
> (input)) */
> +/* #define CVMX_EXTUP(result,input,pos,len) 
> CVMX_EXTU(result,input,pos,(len)-1) */
> +
> +#define CVMX_CINS(result,input,pos,lenm1) asm ("cins %[rt],%[rs]," 
> CVMX_TMP_STR(pos) "," CVMX_TMP_STR(lenm1) : [rt] "=d" (result) : [rs] "d" 
> (input))
> +#define CVMX_CINSP(result,input,pos,len) CVMX_CINS(result,input,pos,(len)-1)
> +
> +#define CVMX_DINS(result,input,pos,len) asm ("dins %[rt],%[rs]," 
> CVMX_TMP_STR(pos) "," CVMX_TMP_STR(len): [rt] "=d" (result): [rs] "d" 
> (input), "[rt]" (result))
> +#define CVMX_DINSM1(result,input,pos,lenm1) 
> CVMX_DINS(result,input,pos,(lenm1)+1)
> +#define CVMX_DINSC(result,pos,len) asm ("dins %[rt],$0," CVMX_TMP_STR(pos) 
> "," CVMX_TMP_STR(len): [rt] "=d" (result): "[rt]" (result))
> +#define CVMX_DINSCM1(result,pos,lenm1) CVMX_DINSC(result,pos,(lenm1)+1)
> +
> +#define CVMX_INS(result,input,pos,len) asm ("ins %[rt],%[rs]," 
> CVMX_TMP_STR(pos) "," CVMX_TMP_STR(len): [rt] "=d" (result): [rs] "d" 
> (input), "[rt]" (result))
> +#define CVMX_INSM1(result,input,pos,lenm1) 
> CVMX_INS(result,input,pos,(lenm1)+1)
> +#define CVMX_INSC(result,pos,len) asm ("ins %[rt],$0," CVMX_TMP_STR(pos) "," 
> CVMX_TMP_STR(len): [rt] "=d" (result): "[rt]" (result))
> +#define CVMX_INSCM1(result,pos,lenm1) CVMX_INSC(result,pos,(lenm1)+1)
> +
> +/* removed */
> +/* #define CVMX_INS0(result,input,pos,lenm1) asm("ins0 %[rt],%[rs]," 
> CVMX_TMP_STR(pos) "," CVMX_TMP_STR(lenm1): [rt] "=d" (result): [rs] "d" 
> (input), "[rt]" (result)) */
> +/* #define CVMX_INS0P(result,input,pos,len) 
> CVMX_INS0(result,input,pos,(len)-1) */
> +/* #define CVMX_INS0C(result,pos,lenm1) asm ("ins0 %[rt],$0," 
> CVMX_TMP_STR(pos) "," CVMX_TMP_STR(lenm1) : [rt] "=d" (result) : "[rt]" 
> (result)) */
> +/* #define CVMX_INS0CP(result,pos,len) CVMX_INS0C(result,pos,(len)-1) */
> +
> +#define CVMX_CLZ(result, input) asm ("clz %[rd],%[rs]" : [rd] "=d" (result) 
> : [rs] "d" (input))
> +#define CVMX_DCLZ(result, input) asm ("dclz %[rd],%[rs]" : [rd] "=d" 
> (result) : [rs] "d" (input))
> +#define CVMX_CLO(result, input) asm ("clo %[rd],%[rs]" : [rd] "=d" (result) 
> : [rs] "d" (input))
> +#define CVMX_DCLO(result, input) asm ("dclo %[rd],%[rs]" : [rd] "=d" 
> (result) : [rs] "d" (input))
> +#define CVMX_POP(result, input) asm ("pop %[rd],%[rs]" : [rd] "=d" (result) 
> : [rs] "d" (input))
> +#define CVMX_DPOP(result, input) asm ("dpop %[rd],%[rs]" : [rd] "=d" 
> (result) : [rs] "d" (input))
> +
> +/* some new cop0-like stuff */
> +#define CVMX_RDHWR(result, regstr) asm volatile ("rdhwr %[rt],$" 
> CVMX_TMP_STR(regstr) : [rt] "=d" (result))
> +#define CVMX_RDHWRNV(result, regstr) asm ("rdhwr %[rt],$" 
> CVMX_TMP_STR(regstr) : [rt] "=d" (result))
> +#define CVMX_DI(result) asm volatile ("di %[rt]" : [rt] "=d" (result))
> +#define CVMX_DI_NULL asm volatile ("di")
> +#define CVMX_EI(result) asm volatile ("ei %[rt]" : [rt] "=d" (result))
> +#define CVMX_EI_NULL asm volatile ("ei")
> +#define CVMX_EHB asm volatile ("ehb")
> +
> +/* mul stuff */
> +#define CVMX_MTM0(m) asm volatile ("mtm0 %[rs]" : : [rs] "d" (m))
> +#define CVMX_MTM1(m) asm volatile ("mtm1 %[rs]" : : [rs] "d" (m))
> +#define CVMX_MTM2(m) asm volatile ("mtm2 %[rs]" : : [rs] "d" (m))
> +#define CVMX_MTP0(p) asm volatile ("mtp0 %[rs]" : : [rs] "d" (p))
> +#define CVMX_MTP1(p) asm volatile ("mtp1 %[rs]" : : [rs] "d" (p))
> +#define CVMX_MTP2(p) asm volatile ("mtp2 %[rs]" : : [rs] "d" (p))
> +#define CVMX_VMULU(dest,mpcand,accum) asm volatile ("vmulu 
> %[rd],%[rs],%[rt]" : [rd] "=d" (dest) : [rs] "d" (mpcand), [rt] "d" (accum))
> +#define CVMX_VMM0(dest,mpcand,accum) asm volatile ("vmm0 %[rd],%[rs],%[rt]" 
> : [rd] "=d" (dest) : [rs] "d" (mpcand), [rt] "d" (accum))
> +#define CVMX_V3MULU(dest,mpcand,accum) asm volatile ("v3mulu 
> %[rd],%[rs],%[rt]" : [rd] "=d" (dest) : [rs] "d" (mpcand), [rt] "d" (accum))
> +
> +/* branch stuff */
> +/* these are hard to make work because the compiler does not realize that 
> the */
> +/* instruction is a branch so may optimize away the label */
> +/* the labels to these next two macros must not include a ":" at the end */
> +#define CVMX_BBIT1(var, pos, label) asm volatile ("bbit1 %[rs]," 
> CVMX_TMP_STR(pos) "," CVMX_TMP_STR(label) : : [rs] "d" (var))
> +#define CVMX_BBIT0(var, pos, label) asm volatile ("bbit0 %[rs]," 
> CVMX_TMP_STR(pos) "," CVMX_TMP_STR(label) : : [rs] "d" (var))
> +/* the label to this macro must include a ":" at the end */
> +#define CVMX_ASM_LABEL(label) label \
> +                             asm volatile (CVMX_TMP_STR(label) : : )
> +
> +/* */
> +/* Low-latency memory stuff */
> +/* */
> +/* set can be 0-1 */
> +#define CVMX_MT_LLM_READ_ADDR(set,val)    asm volatile ("dmtc2 
> %[rt],0x0400+(8*(" CVMX_TMP_STR(set) "))" : : [rt] "d" (val))
> +#define CVMX_MT_LLM_WRITE_ADDR_INTERNAL(set,val)   asm volatile ("dmtc2 
> %[rt],0x0401+(8*(" CVMX_TMP_STR(set) "))" : : [rt] "d" (val))
> +#define CVMX_MT_LLM_READ64_ADDR(set,val)  asm volatile ("dmtc2 
> %[rt],0x0404+(8*(" CVMX_TMP_STR(set) "))" : : [rt] "d" (val))
> +#define CVMX_MT_LLM_WRITE64_ADDR_INTERNAL(set,val) asm volatile ("dmtc2 
> %[rt],0x0405+(8*(" CVMX_TMP_STR(set) "))" : : [rt] "d" (val))
> +#define CVMX_MT_LLM_DATA(set,val)         asm volatile ("dmtc2 
> %[rt],0x0402+(8*(" CVMX_TMP_STR(set) "))" : : [rt] "d" (val))
> +#define CVMX_MF_LLM_DATA(set,val)         asm volatile ("dmfc2 
> %[rt],0x0402+(8*(" CVMX_TMP_STR(set) "))" : [rt] "=d" (val) : )
> +
> +/* load linked, store conditional */
> +#define CVMX_LL(dest, address, offset) asm volatile ("ll %[rt], " 
> CVMX_TMP_STR(offset) "(%[rbase])" : [rt] "=d" (dest) : [rbase] "d" (address))
> +#define CVMX_LLD(dest, address, offset) asm volatile ("lld %[rt], " 
> CVMX_TMP_STR(offset) "(%[rbase])" : [rt] "=d" (dest) : [rbase] "d" (address))
> +#define CVMX_SC(srcdest, address, offset) asm volatile ("sc %[rt], " 
> CVMX_TMP_STR(offset) "(%[rbase])" : [rt] "=d" (srcdest) : [rbase] "d" 
> (address), "[rt]" (srcdest))
> +#define CVMX_SCD(srcdest, address, offset) asm volatile ("scd %[rt], " 
> CVMX_TMP_STR(offset) "(%[rbase])" : [rt] "=d" (srcdest) : [rbase] "d" 
> (address), "[rt]" (srcdest))
> +
> +/* load/store word left/right */
> +#define CVMX_LWR(srcdest, address, offset) asm volatile ("lwr %[rt], " 
> CVMX_TMP_STR(offset) "(%[rbase])" : [rt] "=d" (srcdest) : [rbase] "d" 
> (address), "[rt]" (srcdest))
> +#define CVMX_LWL(srcdest, address, offset) asm volatile ("lwl %[rt], " 
> CVMX_TMP_STR(offset) "(%[rbase])" : [rt] "=d" (srcdest) : [rbase] "d" 
> (address), "[rt]" (srcdest))
> +#define CVMX_LDR(srcdest, address, offset) asm volatile ("ldr %[rt], " 
> CVMX_TMP_STR(offset) "(%[rbase])" : [rt] "=d" (srcdest) : [rbase] "d" 
> (address), "[rt]" (srcdest))
> +#define CVMX_LDL(srcdest, address, offset) asm volatile ("ldl %[rt], " 
> CVMX_TMP_STR(offset) "(%[rbase])" : [rt] "=d" (srcdest) : [rbase] "d" 
> (address), "[rt]" (srcdest))
> +
> +#define CVMX_SWR(src, address, offset) asm volatile ("swr %[rt], " 
> CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address), [rt] "d" (src))
> +#define CVMX_SWL(src, address, offset) asm volatile ("swl %[rt], " 
> CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address), [rt] "d" (src))
> +#define CVMX_SDR(src, address, offset) asm volatile ("sdr %[rt], " 
> CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address), [rt] "d" (src))
> +#define CVMX_SDL(src, address, offset) asm volatile ("sdl %[rt], " 
> CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address), [rt] "d" (src))
> +
> +/* */
> +/* Useful crypto ASM's */
> +/* */
> +
> +/* CRC */
> +
> +#define CVMX_MT_CRC_POLYNOMIAL(val)         asm volatile ("dmtc2 
> %[rt],0x4200" : : [rt] "d" (val))
> +#define CVMX_MT_CRC_IV(val)                 asm volatile ("dmtc2 
> %[rt],0x0201" : : [rt] "d" (val))
> +#define CVMX_MT_CRC_LEN(val)                asm volatile ("dmtc2 
> %[rt],0x1202" : : [rt] "d" (val))
> +#define CVMX_MT_CRC_BYTE(val)               asm volatile ("dmtc2 
> %[rt],0x0204" : : [rt] "d" (val))
> +#define CVMX_MT_CRC_HALF(val)               asm volatile ("dmtc2 
> %[rt],0x0205" : : [rt] "d" (val))
> +#define CVMX_MT_CRC_WORD(val)               asm volatile ("dmtc2 
> %[rt],0x0206" : : [rt] "d" (val))
> +#define CVMX_MT_CRC_DWORD(val)              asm volatile ("dmtc2 
> %[rt],0x1207" : : [rt] "d" (val))
> +#define CVMX_MT_CRC_VAR(val)                asm volatile ("dmtc2 
> %[rt],0x1208" : : [rt] "d" (val))
> +#define CVMX_MT_CRC_POLYNOMIAL_REFLECT(val) asm volatile ("dmtc2 
> %[rt],0x4210" : : [rt] "d" (val))
> +#define CVMX_MT_CRC_IV_REFLECT(val)         asm volatile ("dmtc2 
> %[rt],0x0211" : : [rt] "d" (val))
> +#define CVMX_MT_CRC_BYTE_REFLECT(val)       asm volatile ("dmtc2 
> %[rt],0x0214" : : [rt] "d" (val))
> +#define CVMX_MT_CRC_HALF_REFLECT(val)       asm volatile ("dmtc2 
> %[rt],0x0215" : : [rt] "d" (val))
> +#define CVMX_MT_CRC_WORD_REFLECT(val)       asm volatile ("dmtc2 
> %[rt],0x0216" : : [rt] "d" (val))
> +#define CVMX_MT_CRC_DWORD_REFLECT(val)      asm volatile ("dmtc2 
> %[rt],0x1217" : : [rt] "d" (val))
> +#define CVMX_MT_CRC_VAR_REFLECT(val)        asm volatile ("dmtc2 
> %[rt],0x1218" : : [rt] "d" (val))
> +
> +#define CVMX_MF_CRC_POLYNOMIAL(val)         asm volatile ("dmfc2 
> %[rt],0x0200" : [rt] "=d" (val) : )
> +#define CVMX_MF_CRC_IV(val)                 asm volatile ("dmfc2 
> %[rt],0x0201" : [rt] "=d" (val) : )
> +#define CVMX_MF_CRC_IV_REFLECT(val)         asm volatile ("dmfc2 
> %[rt],0x0203" : [rt] "=d" (val) : )
> +#define CVMX_MF_CRC_LEN(val)                asm volatile ("dmfc2 
> %[rt],0x0202" : [rt] "=d" (val) : )
> +
> +/* MD5 and SHA-1 */
> +
> +/* pos can be 0-6 */
> +#define CVMX_MT_HSH_DAT(val, pos)    asm volatile ("dmtc2 %[rt],0x0040+" 
> CVMX_TMP_STR(pos) :                 : [rt] "d" (val))
> +#define CVMX_MT_HSH_DATZ(pos)       asm volatile ("dmtc2    $0,0x0040+" 
> CVMX_TMP_STR(pos) :                 :               )
> +/* pos can be 0-14 */
> +#define CVMX_MT_HSH_DATW(val, pos)   asm volatile ("dmtc2 %[rt],0x0240+" 
> CVMX_TMP_STR(pos) :                 : [rt] "d" (val))
> +#define CVMX_MT_HSH_DATWZ(pos)      asm volatile ("dmtc2    $0,0x0240+" 
> CVMX_TMP_STR(pos) :                 :               )
> +#define CVMX_MT_HSH_STARTMD5(val)   asm volatile ("dmtc2 %[rt],0x4047"       
>             :                 : [rt] "d" (val))
> +#define CVMX_MT_HSH_STARTSHA(val)   asm volatile ("dmtc2 %[rt],0x4057"       
>             :                 : [rt] "d" (val))
> +#define CVMX_MT_HSH_STARTSHA256(val)   asm volatile ("dmtc2 %[rt],0x404f"    
>                :                 : [rt] "d" (val))
> +#define CVMX_MT_HSH_STARTSHA512(val)   asm volatile ("dmtc2 %[rt],0x424f"    
>                :                 : [rt] "d" (val))
> +/* pos can be 0-3 */
> +#define CVMX_MT_HSH_IV(val, pos)     asm volatile ("dmtc2 %[rt],0x0048+" 
> CVMX_TMP_STR(pos) :                 : [rt] "d" (val))
> +/* pos can be 0-7 */
> +#define CVMX_MT_HSH_IVW(val, pos)     asm volatile ("dmtc2 %[rt],0x0250+" 
> CVMX_TMP_STR(pos) :                 : [rt] "d" (val))
> +
> +/* pos can be 0-6 */
> +#define CVMX_MF_HSH_DAT(val, pos)    asm volatile ("dmfc2 %[rt],0x0040+" 
> CVMX_TMP_STR(pos) : [rt] "=d" (val) :               )
> +/* pos can be 0-14 */
> +#define CVMX_MF_HSH_DATW(val, pos)   asm volatile ("dmfc2 %[rt],0x0240+" 
> CVMX_TMP_STR(pos) : [rt] "=d" (val) :               )
> +/* pos can be 0-3 */
> +#define CVMX_MF_HSH_IV(val, pos)     asm volatile ("dmfc2 %[rt],0x0048+" 
> CVMX_TMP_STR(pos) : [rt] "=d" (val) :               )
> +/* pos can be 0-7 */
> +#define CVMX_MF_HSH_IVW(val, pos)     asm volatile ("dmfc2 %[rt],0x0250+" 
> CVMX_TMP_STR(pos) : [rt] "=d" (val) :               )
> +
> +/* 3DES */
> +
> +/* pos can be 0-2 */
> +#define CVMX_MT_3DES_KEY(val, pos)   asm volatile ("dmtc2 %[rt],0x0080+" 
> CVMX_TMP_STR(pos) :                 : [rt] "d" (val))
> +#define CVMX_MT_3DES_IV(val)        asm volatile ("dmtc2 %[rt],0x0084"       
>             :                 : [rt] "d" (val))
> +#define CVMX_MT_3DES_ENC_CBC(val)   asm volatile ("dmtc2 %[rt],0x4088"       
>             :                 : [rt] "d" (val))
> +#define CVMX_MT_3DES_ENC(val)       asm volatile ("dmtc2 %[rt],0x408a"       
>             :                 : [rt] "d" (val))
> +#define CVMX_MT_3DES_DEC_CBC(val)   asm volatile ("dmtc2 %[rt],0x408c"       
>             :                 : [rt] "d" (val))
> +#define CVMX_MT_3DES_DEC(val)       asm volatile ("dmtc2 %[rt],0x408e"       
>             :                 : [rt] "d" (val))
> +#define CVMX_MT_3DES_RESULT(val)    asm volatile ("dmtc2 %[rt],0x0098"       
>             :                 : [rt] "d" (val))
> +
> +/* pos can be 0-2 */
> +#define CVMX_MF_3DES_KEY(val, pos)   asm volatile ("dmfc2 %[rt],0x0080+" 
> CVMX_TMP_STR(pos) : [rt] "=d" (val) :               )
> +#define CVMX_MF_3DES_IV(val)        asm volatile ("dmfc2 %[rt],0x0084"       
>             : [rt] "=d" (val) :               )
> +#define CVMX_MF_3DES_RESULT(val)    asm volatile ("dmfc2 %[rt],0x0088"       
>             : [rt] "=d" (val) :               )
> +
> +/* KASUMI */
> +
> +/* pos can be 0-1 */
> +#define CVMX_MT_KAS_KEY(val, pos)    CVMX_MT_3DES_KEY(val, pos)
> +#define CVMX_MT_KAS_ENC_CBC(val)    asm volatile ("dmtc2 %[rt],0x4089"       
>             :                 : [rt] "d" (val))
> +#define CVMX_MT_KAS_ENC(val)        asm volatile ("dmtc2 %[rt],0x408b"       
>             :                 : [rt] "d" (val))
> +#define CVMX_MT_KAS_RESULT(val)     CVMX_MT_3DES_RESULT(val)
> +
> +/* pos can be 0-1 */
> +#define CVMX_MF_KAS_KEY(val, pos)    CVMX_MF_3DES_KEY(val, pos)
> +#define CVMX_MF_KAS_RESULT(val)     CVMX_MF_3DES_RESULT(val)
> +
> +/* AES */
> +
> +#define CVMX_MT_AES_ENC_CBC0(val)   asm volatile ("dmtc2 %[rt],0x0108"       
>             :                 : [rt] "d" (val))
> +#define CVMX_MT_AES_ENC_CBC1(val)   asm volatile ("dmtc2 %[rt],0x3109"       
>             :                 : [rt] "d" (val))
> +#define CVMX_MT_AES_ENC0(val)       asm volatile ("dmtc2 %[rt],0x010a"       
>             :                 : [rt] "d" (val))
> +#define CVMX_MT_AES_ENC1(val)       asm volatile ("dmtc2 %[rt],0x310b"       
>             :                 : [rt] "d" (val))
> +#define CVMX_MT_AES_DEC_CBC0(val)   asm volatile ("dmtc2 %[rt],0x010c"       
>             :                 : [rt] "d" (val))
> +#define CVMX_MT_AES_DEC_CBC1(val)   asm volatile ("dmtc2 %[rt],0x310d"       
>             :                 : [rt] "d" (val))
> +#define CVMX_MT_AES_DEC0(val)       asm volatile ("dmtc2 %[rt],0x010e"       
>             :                 : [rt] "d" (val))
> +#define CVMX_MT_AES_DEC1(val)       asm volatile ("dmtc2 %[rt],0x310f"       
>             :                 : [rt] "d" (val))
> +/* pos can be 0-3 */
> +#define CVMX_MT_AES_KEY(val, pos)    asm volatile ("dmtc2 %[rt],0x0104+" 
> CVMX_TMP_STR(pos) :                 : [rt] "d" (val))
> +/* pos can be 0-1 */
> +#define CVMX_MT_AES_IV(val, pos)     asm volatile ("dmtc2 %[rt],0x0102+" 
> CVMX_TMP_STR(pos) :                 : [rt] "d" (val))
> +#define CVMX_MT_AES_KEYLENGTH(val)  asm volatile ("dmtc2 %[rt],0x0110"       
>             :                 : [rt] "d" (val)) /* write the keylen */
> +/* pos can be 0-1 */
> +#define CVMX_MT_AES_RESULT(val, pos) asm volatile ("dmtc2 %[rt],0x0100+" 
> CVMX_TMP_STR(pos) :                 : [rt] "d" (val))
> +
> +/* pos can be 0-1 */
> +#define CVMX_MF_AES_RESULT(val, pos) asm volatile ("dmfc2 %[rt],0x0100+" 
> CVMX_TMP_STR(pos) : [rt] "=d" (val) :               )
> +/* pos can be 0-1 */
> +#define CVMX_MF_AES_IV(val, pos)     asm volatile ("dmfc2 %[rt],0x0102+" 
> CVMX_TMP_STR(pos) : [rt] "=d" (val) :               )
> +/* pos can be 0-3 */
> +#define CVMX_MF_AES_KEY(val, pos)    asm volatile ("dmfc2 %[rt],0x0104+" 
> CVMX_TMP_STR(pos) : [rt] "=d" (val) :               )
> +#define CVMX_MF_AES_KEYLENGTH(val)  asm volatile ("dmfc2 %[rt],0x0110"       
>             : [rt] "=d" (val) :               ) /* read the keylen */
> +#define CVMX_MF_AES_DAT0(val)       asm volatile ("dmfc2 %[rt],0x0111"       
>             : [rt] "=d" (val) :               ) /* first piece of input data 
> */
> +/* GFM COP2 macros */
> +/* index can be 0 or 1 */
> +#define CVMX_MF_GFM_MUL(val, index)     asm volatile ("dmfc2 %[rt],0x0258+" 
> CVMX_TMP_STR(index) : [rt] "=d" (val) :               )
> +#define CVMX_MF_GFM_POLY(val)           asm volatile ("dmfc2 %[rt],0x025e"   
>                    : [rt] "=d" (val) :               )
> +#define CVMX_MF_GFM_RESINP(val, index)  asm volatile ("dmfc2 %[rt],0x025a+" 
> CVMX_TMP_STR(index) : [rt] "=d" (val) :               )
> +
> +#define CVMX_MT_GFM_MUL(val, index)     asm volatile ("dmtc2 %[rt],0x0258+" 
> CVMX_TMP_STR(index) :                 : [rt] "d" (val))
> +#define CVMX_MT_GFM_POLY(val)           asm volatile ("dmtc2 %[rt],0x025e"   
>                    :                 : [rt] "d" (val))
> +#define CVMX_MT_GFM_RESINP(val, index)  asm volatile ("dmtc2 %[rt],0x025a+" 
> CVMX_TMP_STR(index) :                 : [rt] "d" (val))
> +#define CVMX_MT_GFM_XOR0(val)           asm volatile ("dmtc2 %[rt],0x025c"   
>                    :                 : [rt] "d" (val))
> +#define CVMX_MT_GFM_XORMUL1(val)        asm volatile ("dmtc2 %[rt],0x425d"   
>                    :                 : [rt] "d" (val))
> +
> +/* check_ordering stuff */
> +#if 0
> +#define CVMX_MF_CHORD(dest)         asm volatile ("dmfc2 %[rt],0x400" : [rt] 
> "=d" (dest) : )
> +#else
> +#define CVMX_MF_CHORD(dest)         CVMX_RDHWR(dest, 30)
> +#endif
> +
> +#if 0
> +#define CVMX_MF_CYCLE(dest)         asm volatile ("dmfc0 %[rt],$9,6" : [rt] 
> "=d" (dest) : )  /* Use (64-bit) CvmCount register rather than Count */
> +#else
> +#define CVMX_MF_CYCLE(dest)         CVMX_RDHWR(dest, 31)     /* reads the 
> current (64-bit) CvmCount value */
> +#endif
> +
> +#define CVMX_MT_CYCLE(src)         asm volatile ("dmtc0 %[rt],$9,6" :: [rt] 
> "d" (src))
> +
> +#define CVMX_MF_CACHE_ERR(val)            asm volatile ("dmfc0 %[rt],$27,0" 
> :  [rt] "=d" (val):)
> +#define CVMX_MF_DCACHE_ERR(val)           asm volatile ("dmfc0 %[rt],$27,1" 
> :  [rt] "=d" (val):)
> +#define CVMX_MF_CVM_MEM_CTL(val)          asm volatile ("dmfc0 %[rt],$11,7" 
> :  [rt] "=d" (val):)
> +#define CVMX_MF_CVM_CTL(val)              asm volatile ("dmfc0 %[rt],$9,7"  
> :  [rt] "=d" (val):)
> +#define CVMX_MT_CACHE_ERR(val)            asm volatile ("dmtc0 %[rt],$27,0" 
> : : [rt] "d" (val))
> +#define CVMX_MT_DCACHE_ERR(val)           asm volatile ("dmtc0 %[rt],$27,1" 
> : : [rt] "d" (val))
> +#define CVMX_MT_CVM_MEM_CTL(val)          asm volatile ("dmtc0 %[rt],$11,7" 
> : : [rt] "d" (val))
> +#define CVMX_MT_CVM_CTL(val)              asm volatile ("dmtc0 %[rt],$9,7"  
> : : [rt] "d" (val))
> +
> +/* Macros for TLB */
> +#define CVMX_TLBWI                       asm volatile ("tlbwi" : : )
> +#define CVMX_TLBWR                       asm volatile ("tlbwr" : : )
> +#define CVMX_TLBR                        asm volatile ("tlbr" : : )
> +#define CVMX_MT_ENTRY_HIGH(val)          asm volatile ("dmtc0 %[rt],$10,0" : 
> : [rt] "d" (val))
> +#define CVMX_MT_ENTRY_LO_0(val)          asm volatile ("dmtc0 %[rt],$2,0" : 
> : [rt] "d" (val))
> +#define CVMX_MT_ENTRY_LO_1(val)          asm volatile ("dmtc0 %[rt],$3,0" : 
> : [rt] "d" (val))
> +#define CVMX_MT_PAGEMASK(val)            asm volatile ("mtc0 %[rt],$5,0" : : 
> [rt] "d" (val))
> +#define CVMX_MT_PAGEGRAIN(val)           asm volatile ("mtc0 %[rt],$5,1" : : 
> [rt] "d" (val))
> +#define CVMX_MT_TLB_INDEX(val)           asm volatile ("mtc0 %[rt],$0,0" : : 
> [rt] "d" (val))
> +#define CVMX_MT_TLB_CONTEXT(val)         asm volatile ("dmtc0 %[rt],$4,0" : 
> : [rt] "d" (val))
> +#define CVMX_MT_TLB_WIRED(val)           asm volatile ("mtc0 %[rt],$6,0" : : 
> [rt] "d" (val))
> +#define CVMX_MT_TLB_RANDOM(val)          asm volatile ("mtc0 %[rt],$1,0" : : 
> [rt] "d" (val))
> +#define CVMX_MF_ENTRY_LO_0(val)          asm volatile ("dmfc0 %[rt],$2,0" :  
> [rt] "=d" (val):)
> +#define CVMX_MF_ENTRY_LO_1(val)          asm volatile ("dmfc0 %[rt],$3,0" :  
> [rt] "=d" (val):)
> +#define CVMX_MF_ENTRY_HIGH(val)          asm volatile ("dmfc0 %[rt],$10,0" : 
>  [rt] "=d" (val):)
> +#define CVMX_MF_PAGEMASK(val)            asm volatile ("mfc0 %[rt],$5,0" :  
> [rt] "=d" (val):)
> +#define CVMX_MF_PAGEGRAIN(val)           asm volatile ("mfc0 %[rt],$5,1" :  
> [rt] "=d" (val):)
> +#define CVMX_MF_TLB_WIRED(val)           asm volatile ("mfc0 %[rt],$6,0" :  
> [rt] "=d" (val):)
> +#define CVMX_MF_TLB_RANDOM(val)          asm volatile ("mfc0 %[rt],$1,0" :  
> [rt] "=d" (val):)
> +#define TLB_DIRTY   (0x1ULL<<2)
> +#define TLB_VALID   (0x1ULL<<1)
> +#define TLB_GLOBAL  (0x1ULL<<0)
> +
> +/* assembler macros to guarantee byte loads/stores are used */
> +/* for an unaligned 16-bit access (these use AT register) */
> +/* we need the hidden argument (__a) so that GCC gets the dependencies right 
> */
> +#define CVMX_LOADUNA_INT16(result, address, offset) \
> +     { char *__a = (char *)(address); \
> +       asm ("ulh %[rdest], " CVMX_TMP_STR(offset) "(%[rbase])" : [rdest] 
> "=d" (result) : [rbase] "d" (__a), "m"(__a[offset]), "m"(__a[offset + 1])); }
> +#define CVMX_LOADUNA_UINT16(result, address, offset) \
> +     { char *__a = (char *)(address); \
> +       asm ("ulhu %[rdest], " CVMX_TMP_STR(offset) "(%[rbase])" : [rdest] 
> "=d" (result) : [rbase] "d" (__a), "m"(__a[offset + 0]), "m"(__a[offset + 
> 1])); }
> +#define CVMX_STOREUNA_INT16(data, address, offset) \
> +     { char *__a = (char *)(address); \
> +       asm ("ush %[rsrc], " CVMX_TMP_STR(offset) "(%[rbase])" : 
> "=m"(__a[offset + 0]), "=m"(__a[offset + 1]): [rsrc] "d" (data), [rbase] "d" 
> (__a)); }
> +
> +#define CVMX_LOADUNA_INT32(result, address, offset) \
> +     { char *__a = (char *)(address); \
> +       asm ("ulw %[rdest], " CVMX_TMP_STR(offset) "(%[rbase])" : [rdest] 
> "=d" (result) : \
> +            [rbase] "d" (__a), "m"(__a[offset + 0]), "m"(__a[offset + 1]), 
> "m"(__a[offset + 2]), "m"(__a[offset + 3])); }
> +#define CVMX_STOREUNA_INT32(data, address, offset) \
> +     { char *__a = (char *)(address); \
> +       asm ("usw %[rsrc], " CVMX_TMP_STR(offset) "(%[rbase])" : \
> +            "=m"(__a[offset + 0]), "=m"(__a[offset + 1]), "=m"(__a[offset + 
> 2]), "=m"(__a[offset + 3]) : \
> +            [rsrc] "d" (data), [rbase] "d" (__a)); }
> +
> +#define CVMX_LOADUNA_INT64(result, address, offset) \
> +     { char *__a = (char *)(address); \
> +       asm ("uld %[rdest], " CVMX_TMP_STR(offset) "(%[rbase])" : [rdest] 
> "=d" (result) : \
> +            [rbase] "d" (__a), "m"(__a[offset + 0]), "m"(__a[offset + 1]), 
> "m"(__a[offset + 2]), "m"(__a[offset + 3]), \
> +            "m"(__a[offset + 4]), "m"(__a[offset + 5]), "m"(__a[offset + 
> 6]), "m"(__a[offset + 7])); }
> +#define CVMX_STOREUNA_INT64(data, address, offset) \
> +     { char *__a = (char *)(address); \
> +       asm ("usd %[rsrc], " CVMX_TMP_STR(offset) "(%[rbase])" : \
> +            "=m"(__a[offset + 0]), "=m"(__a[offset + 1]), "=m"(__a[offset + 
> 2]), "=m"(__a[offset + 3]), \
> +            "=m"(__a[offset + 4]), "=m"(__a[offset + 5]), "=m"(__a[offset + 
> 6]), "=m"(__a[offset + 7]) : \
> +            [rsrc] "d" (data), [rbase] "d" (__a)); }
> +
> +#endif /* __CVMX_ASM_H__ */
> diff --git a/arch/mips/cavium-octeon/executive/cvmx-bootinfo.h 
> b/arch/mips/cavium-octeon/executive/cvmx-bootinfo.h
> new file mode 100644
> index 0000000..acd1c57
> --- /dev/null
> +++ b/arch/mips/cavium-octeon/executive/cvmx-bootinfo.h
> @@ -0,0 +1,238 @@
> +/***********************license start***************
> + * Author: Cavium Networks
> + *
> + * Contact: support@caviumnetworks.com
> + * This file is part of the OCTEON SDK
> + *
> + * Copyright (c) 2003-2008 Cavium Networks
> + *
> + * This file is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, Version 2, as 
> published by
> + * the Free Software Foundation.
> + *
> + * This file is distributed in the hope that it will be useful,
> + * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 
> NONINFRINGEMENT.
> + * See the GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this file; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + * or visit http://www.gnu.org/licenses/.
> + *
> + * This file may also be available under a different license from Cavium.
> + * Contact Cavium Networks for more information
> + ***********************license end**************************************/
> +
> +/**
> + * @file
> + * Header file containing the ABI with the bootloader.
> + *
> + */
> +
> +#ifndef __CVMX_BOOTINFO_H__
> +#define __CVMX_BOOTINFO_H__
> +
> +/* Current major and minor versions of the CVMX bootinfo block that is
> +** passed from the bootloader to the application.  This is versioned
> +** so that applications can properly handle multiple bootloader
> +** versions. */
> +#define CVMX_BOOTINFO_MAJ_VER 1
> +#define CVMX_BOOTINFO_MIN_VER 2
> +
> +#if (CVMX_BOOTINFO_MAJ_VER == 1)
> +#define CVMX_BOOTINFO_OCTEON_SERIAL_LEN 20
> +/* This structure is populated by the bootloader.  For binary
> +** compatibility the only changes that should be made are
> +** adding members to the end of the structure, and the minor
> +** version should be incremented at that time.
> +** If an incompatible change is made, the major version
> +** must be incremented, and the minor version should be reset
> +** to 0.
> +*/
> +typedef struct {
> +     uint32_t major_version;
> +     uint32_t minor_version;
> +
> +     uint64_t stack_top;
> +     uint64_t heap_base;
> +     uint64_t heap_end;
> +     uint64_t desc_vaddr;
> +
> +     uint32_t exception_base_addr;
> +     uint32_t stack_size;
> +     uint32_t flags;
> +     uint32_t core_mask;
> +     uint32_t dram_size;
> +                      /**< DRAM size in megabytes */
> +     uint32_t phy_mem_desc_addr;
> +                              /**< physical address of free memory 
> descriptor block*/
> +     uint32_t debugger_flags_base_addr;
> +                                     /**< used to pass flags from app to 
> debugger */
> +     uint32_t eclock_hz;
> +                      /**< CPU clock speed, in hz */
> +     uint32_t dclock_hz;
> +                      /**< DRAM clock speed, in hz */
> +     uint32_t reserved0;
> +     uint16_t board_type;
> +     uint8_t board_rev_major;
> +     uint8_t board_rev_minor;
> +     uint16_t reserved1;
> +     uint8_t reserved2;
> +     uint8_t reserved3;
> +     char board_serial_number[CVMX_BOOTINFO_OCTEON_SERIAL_LEN];
> +     uint8_t mac_addr_base[6];
> +     uint8_t mac_addr_count;
> +#if (CVMX_BOOTINFO_MIN_VER >= 1)
> +     /* Several boards support compact flash on the Octeon boot bus.  The CF
> +      ** memory spaces may be mapped to different addresses on different 
> boards.
> +      ** These are the physical addresses, so care must be taken to use the 
> correct
> +      ** XKPHYS/KSEG0 addressing depending on the application's ABI.
> +      ** These values will be 0 if CF is not present */
> +     uint64_t compact_flash_common_base_addr;
> +     uint64_t compact_flash_attribute_base_addr;
> +     /* Base address of the LED display (as on EBT3000 board)
> +      ** This will be 0 if LED display not present. */
> +     uint64_t led_display_base_addr;
> +#endif
> +#if (CVMX_BOOTINFO_MIN_VER >= 2)
> +     uint32_t dfa_ref_clock_hz;
> +     /**< DFA reference clock in hz (if applicable)*/
> +     uint32_t config_flags;
> +     /**< flags indicating various configuration options.  These
> +      ** flags supercede the 'flags' variable and should be used
> +      ** instead if available */
> +#endif
> +
> +} cvmx_bootinfo_t;
> +
> +#define CVMX_BOOTINFO_CFG_FLAG_PCI_HOST                      (1ull << 0)
> +#define CVMX_BOOTINFO_CFG_FLAG_PCI_TARGET            (1ull << 1)
> +#define CVMX_BOOTINFO_CFG_FLAG_DEBUG                 (1ull << 2)
> +#define CVMX_BOOTINFO_CFG_FLAG_NO_MAGIC                      (1ull << 3)
> +/* This flag is set if the TLB mappings are not contained in the
> +** 0x10000000 - 0x20000000 boot bus region. */
> +#define CVMX_BOOTINFO_CFG_FLAG_OVERSIZE_TLB_MAPPING     (1ull << 4)
> +#define CVMX_BOOTINFO_CFG_FLAG_BREAK                 (1ull << 5)
> +
> +#endif /*   (CVMX_BOOTINFO_MAJ_VER == 1) */
> +
> +/* Type defines for board and chip types */
> +enum cvmx_board_types_enum {
> +     CVMX_BOARD_TYPE_NULL = 0,
> +     CVMX_BOARD_TYPE_SIM = 1,
> +     CVMX_BOARD_TYPE_EBT3000 = 2,
> +     CVMX_BOARD_TYPE_KODAMA = 3,
> +     CVMX_BOARD_TYPE_NIAGARA = 4,
> +     CVMX_BOARD_TYPE_NAC38 = 5,      /* formerly NAO38 */
> +     CVMX_BOARD_TYPE_THUNDER = 6,
> +     CVMX_BOARD_TYPE_TRANTOR = 7,
> +     CVMX_BOARD_TYPE_EBH3000 = 8,
> +     CVMX_BOARD_TYPE_EBH3100 = 9,
> +     CVMX_BOARD_TYPE_HIKARI = 10,
> +     CVMX_BOARD_TYPE_CN3010_EVB_HS5 = 11,
> +     CVMX_BOARD_TYPE_CN3005_EVB_HS5 = 12,
> +     CVMX_BOARD_TYPE_KBP = 13,
> +     CVMX_BOARD_TYPE_CN3020_EVB_HS5 = 14,    /* Deprecated, 
> CVMX_BOARD_TYPE_CN3010_EVB_HS5 supports the CN3020 */
> +     CVMX_BOARD_TYPE_EBT5800 = 15,
> +     CVMX_BOARD_TYPE_NICPRO2 = 16,
> +     CVMX_BOARD_TYPE_EBH5600 = 17,
> +     CVMX_BOARD_TYPE_EBH5601 = 18,
> +     CVMX_BOARD_TYPE_EBH5200 = 19,
> +     CVMX_BOARD_TYPE_BBGW_REF = 20,
> +     CVMX_BOARD_TYPE_NIC_XLE_4G = 21,
> +     CVMX_BOARD_TYPE_EBT5600 = 22,
> +     CVMX_BOARD_TYPE_EBH5201 = 23,
> +     CVMX_BOARD_TYPE_MAX,
> +
> +     /* The range from CVMX_BOARD_TYPE_MAX to 
> CVMX_BOARD_TYPE_CUST_DEFINED_MIN is reserved
> +      ** for future SDK use. */
> +
> +     /* Set aside a range for customer boards.  These numbers are managed
> +      ** by Cavium.
> +      */
> +     CVMX_BOARD_TYPE_CUST_DEFINED_MIN = 10000,
> +     CVMX_BOARD_TYPE_CUST_WSX16 = 10001,
> +     CVMX_BOARD_TYPE_CUST_NS0216 = 10002,
> +     CVMX_BOARD_TYPE_CUST_NB5 = 10003,
> +     CVMX_BOARD_TYPE_CUST_WMR500 = 10004,
> +     CVMX_BOARD_TYPE_CUST_DEFINED_MAX = 20000,
> +
> +     /* Set aside a range for customer private use.  The SDK won't
> +      ** use any numbers in this range. */
> +     CVMX_BOARD_TYPE_CUST_PRIVATE_MIN = 20001,
> +     CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000,
> +
> +     /* The remaining range is reserved for future use. */
> +};
> +enum cvmx_chip_types_enum {
> +     CVMX_CHIP_TYPE_NULL = 0,
> +     CVMX_CHIP_SIM_TYPE_DEPRECATED = 1,
> +     CVMX_CHIP_TYPE_OCTEON_SAMPLE = 2,
> +     CVMX_CHIP_TYPE_MAX,
> +};
> +
> +/* Compatability alias for NAC38 name change, planned to be removed from SDK 
> 1.7 */
> +#define CVMX_BOARD_TYPE_NAO38        CVMX_BOARD_TYPE_NAC38
> +
> +/* Functions to return string based on type */
> +#define ENUM_BRD_TYPE_CASE(x)   case x: return(#x + 16);     /* Skip 
> CVMX_BOARD_TYPE_ */
> +static inline const char *cvmx_board_type_to_string(enum
> +                                                 cvmx_board_types_enum type)
> +{
> +     switch (type) {
> +             ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NULL)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_SIM)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT3000)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KODAMA)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIAGARA)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NAC38)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_THUNDER)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_TRANTOR)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH3000)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH3100)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_HIKARI)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3010_EVB_HS5)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3005_EVB_HS5)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KBP)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3020_EVB_HS5)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5800)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NICPRO2)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5600)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5601)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5200)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_BBGW_REF)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC_XLE_4G)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5600)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5201)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_MAX)
> +
> +                 /* Customer boards listed here */
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DEFINED_MIN)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_WSX16)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_NS0216)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_NB5)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_WMR500)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DEFINED_MAX)
> +
> +                 /* Customer private range */
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MIN)
> +                 ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX)
> +     }
> +     return "Unsupported Board";
> +}
> +
> +#define ENUM_CHIP_TYPE_CASE(x)   case x: return(#x + 15);    /* Skip 
> CVMX_CHIP_TYPE */
> +static inline const char *cvmx_chip_type_to_string(enum
> +                                                cvmx_chip_types_enum type)
> +{
> +     switch (type) {
> +             ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_NULL)
> +                 ENUM_CHIP_TYPE_CASE(CVMX_CHIP_SIM_TYPE_DEPRECATED)
> +                 ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_OCTEON_SAMPLE)
> +                 ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_MAX)
> +     }
> +     return "Unsupported Chip";
> +}
> +
> +#endif /* __CVMX_BOOTINFO_H__ */
> diff --git a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c 
> b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
> new file mode 100644
> index 0000000..bb8b087
> --- /dev/null
> +++ b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
> @@ -0,0 +1,897 @@
> +/***********************license start***************
> + * Author: Cavium Networks
> + *
> + * Contact: support@caviumnetworks.com
> + * This file is part of the OCTEON SDK
> + *
> + * Copyright (c) 2003-2008 Cavium Networks
> + *
> + * This file is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, Version 2, as 
> published by
> + * the Free Software Foundation.
> + *
> + * This file is distributed in the hope that it will be useful,
> + * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 
> NONINFRINGEMENT.
> + * See the GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this file; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + * or visit http://www.gnu.org/licenses/.
> + *
> + * This file may also be available under a different license from Cavium.
> + * Contact Cavium Networks for more information
> + ***********************license end**************************************/
> +
> +/**
> + * @file
> + * Simple allocate only memory allocator.  Used to allocate memory at 
> application
> + * start time.
> + *
> + */
> +
> +#include "cvmx.h"
> +#include "cvmx-spinlock.h"
> +#include "cvmx-bootmem.h"
> +
> +/*#define DEBUG */
> +
> +#undef       MAX
> +#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
> +
> +#undef       MIN
> +#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
> +
> +#define ALIGN_ADDR_UP(addr, align)     (((addr) + (~(align))) & (align))
> +
> +static cvmx_bootmem_desc_t *cvmx_bootmem_desc;
> +
> +/* See header file for descriptions of functions */
> +
> +/* Wrapper functions are provided for reading/writing the size and
> + * next block values as these may not be directly addressible (in 32
> + * bit applications, for instance.)  Offsets of data elements in
> + * bootmem list, must match cvmx_bootmem_block_header_t */
> +#define NEXT_OFFSET 0
> +#define SIZE_OFFSET 8
> +static void cvmx_bootmem_phy_set_size(uint64_t addr, uint64_t size)
> +{
> +     cvmx_write64_uint64((addr + SIZE_OFFSET) | (1ull << 63), size);
> +}
> +
> +static void cvmx_bootmem_phy_set_next(uint64_t addr, uint64_t next)
> +{
> +     cvmx_write64_uint64((addr + NEXT_OFFSET) | (1ull << 63), next);
> +}
> +
> +static uint64_t cvmx_bootmem_phy_get_size(uint64_t addr)
> +{
> +     return cvmx_read64_uint64((addr + SIZE_OFFSET) | (1ull << 63));
> +}
> +
> +static uint64_t cvmx_bootmem_phy_get_next(uint64_t addr)
> +{
> +     return cvmx_read64_uint64((addr + NEXT_OFFSET) | (1ull << 63));
> +}
> +
> +void *cvmx_bootmem_alloc_range(uint64_t size, uint64_t alignment,
> +                            uint64_t min_addr, uint64_t max_addr)
> +{
> +     int64_t address;
> +     address =
> +         cvmx_bootmem_phy_alloc(size, min_addr, max_addr, alignment, 0);
> +
> +     if (address > 0)
> +             return cvmx_phys_to_ptr(address);
> +     else
> +             return NULL;
> +}
> +
> +void *cvmx_bootmem_alloc_address(uint64_t size, uint64_t address,
> +                              uint64_t alignment)
> +{
> +     return cvmx_bootmem_alloc_range(size, alignment, address,
> +                                     address + size);
> +}
> +
> +void *cvmx_bootmem_alloc(uint64_t size, uint64_t alignment)
> +{
> +     return cvmx_bootmem_alloc_range(size, alignment, 0, 0);
> +}
> +
> +void *cvmx_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr,
> +                                  uint64_t max_addr, uint64_t align,
> +                                  char *name)
> +{
> +     int64_t addr;
> +
> +     addr =
> +         cvmx_bootmem_phy_named_block_alloc(size, min_addr, max_addr, align,
> +                                            name, 0);
> +     if (addr >= 0)
> +             return cvmx_phys_to_ptr(addr);
> +     else
> +             return NULL;
> +
> +}
> +
> +void *cvmx_bootmem_alloc_named_address(uint64_t size, uint64_t address,
> +                                    char *name)
> +{
> +     return cvmx_bootmem_alloc_named_range (size, address,
> +                                            address + size, 0, name);
> +}
> +
> +void *cvmx_bootmem_alloc_named(uint64_t size, uint64_t alignment, char *name)
> +{
> +     return cvmx_bootmem_alloc_named_range(size, 0, 0, alignment, name);
> +}
> +
> +int cvmx_bootmem_free_named(char *name)
> +{
> +     return cvmx_bootmem_phy_named_block_free(name, 0);
> +}
> +
> +cvmx_bootmem_named_block_desc_t *cvmx_bootmem_find_named_block(char *name)
> +{
> +     return cvmx_bootmem_phy_named_block_find(name, 0);
> +}
> +
> +void cvmx_bootmem_print_named(void)
> +{
> +     cvmx_bootmem_phy_named_block_print();
> +}
> +
> +
> +int cvmx_bootmem_init(void *mem_desc_ptr)
> +{
> +     /* Verify that the size of cvmx_spinlock_t meets our assumptions */
> +     if (sizeof(cvmx_spinlock_t) != 4) {
> +             cvmx_dprintf("ERROR: Unexpected size of cvmx_spinlock_t\n");
> +             return -1;
> +     }
> +
> +     /* Here we set the global pointer to the bootmem descriptor block.  
> This pointer will
> +      ** be used directly, so we will set it up to be directly usable by the 
> application.
> +      ** It is set up as follows for the various runtime/ABI combinations:
> +      ** Linux 64 bit: Set XKPHYS bit
> +      ** Linux 32 bit: use mmap to create mapping, use virtual address
> +      ** CVMX 64 bit:  use physical address directly
> +      ** CVMX 32 bit:  use physical address directly
> +      ** Note that the CVMX environment assumes the use of 1-1 TLB mappings 
> so that the physical addresses
> +      ** can be used directly
> +      */
> +     if (!cvmx_bootmem_desc) {
> +#if   defined(CVMX_ABI_64)
> +             /* Set XKPHYS bit */
> +             cvmx_bootmem_desc = cvmx_phys_to_ptr(CAST64(mem_desc_ptr));
> +#else
> +             cvmx_bootmem_desc = (cvmx_bootmem_desc_t *) mem_desc_ptr;
> +#endif
> +     }
> +
> +     return 0;
> +}
> +
> +uint64_t cvmx_bootmem_available_mem(uint64_t min_block_size)
> +{
> +     return cvmx_bootmem_phy_available_mem(min_block_size);
> +}
> +
> +/*********************************************************************
> +** The cvmx_bootmem_phy* functions below return 64 bit physical addresses,
> +** and expose more features that the cvmx_bootmem_functions above.  These are
> +** required for full memory space access in 32 bit applications, as well as 
> for
> +** using some advance features.
> +** Most applications should not need to use these.
> +**
> +**/
> +
> +int64_t cvmx_bootmem_phy_alloc(uint64_t req_size, uint64_t address_min,
> +                            uint64_t address_max, uint64_t alignment,
> +                            uint32_t flags)
> +{
> +
> +     uint64_t head_addr;
> +     uint64_t ent_addr;
> +     uint64_t prev_addr = 0; /* points to previous list entry, NULL current 
> entry is head of list */
> +     uint64_t new_ent_addr = 0;
> +     uint64_t desired_min_addr;
> +     uint64_t alignment_mask = ~(alignment - 1);
> +
> +#ifdef DEBUG
> +     cvmx_dprintf
> +         ("cvmx_bootmem_phy_alloc: req_size: 0x%llx, min_addr: 0x%llx, 
> max_addr: 0x%llx, align: 0x%llx\n",
> +          (unsigned long long)req_size, (unsigned long long)address_min,
> +          (unsigned long long)address_max, (unsigned long long)alignment);
> +#endif
> +
> +     if (cvmx_bootmem_desc->major_version > 3) {
> +             cvmx_dprintf
> +                 ("ERROR: Incompatible bootmem descriptor version: %d.%d at 
> addr: %p\n",
> +                  (int)cvmx_bootmem_desc->major_version,
> +                  (int)cvmx_bootmem_desc->minor_version, cvmx_bootmem_desc);
> +             goto error_out;
> +     }
> +
> +     /* Do a variety of checks to validate the arguments.  The
> +      * allocator code will later assume that these checks have
> +      * been made.  We validate that the requested constraints are
> +      * not self-contradictory before we look through the list of
> +      * available memory
> +      */
> +
> +     /* 0 is not a valid req_size for this allocator */
> +     if (!req_size)
> +             goto error_out;
> +
> +     /* Round req_size up to mult of minimum alignment bytes */
> +     req_size =
> +         (req_size +
> +          (CVMX_BOOTMEM_ALIGNMENT_SIZE -
> +           1)) & ~(CVMX_BOOTMEM_ALIGNMENT_SIZE - 1);
> +
> +     /* Convert !0 address_min and 0 address_max to special case of
> +      * range that specifies an exact memory block to allocate.
> +      * Do this before other checks and adjustments so that this
> +      * tranformation will be validated */
> +     if (address_min && !address_max)
> +             address_max = address_min + req_size;
> +     else if (!address_min && !address_max)
> +             address_max = ~0ull;    /* If no limits given, use max limits */
> +
> +
> +     /* Enforce minimum alignment (this also keeps the minimum free block
> +      ** req_size the same as the alignment req_size */
> +     if (alignment < CVMX_BOOTMEM_ALIGNMENT_SIZE) {
> +             alignment = CVMX_BOOTMEM_ALIGNMENT_SIZE;
> +     }
> +     alignment_mask = ~(alignment - 1);
> +
> +     /* Adjust address minimum based on requested alignment (round
> +      * up to meet alignment).  Do this here so we can reject
> +      * impossible requests up front. (NOP for address_min ==
> +      * 0) */
> +     if (alignment)
> +             address_min =
> +                 (address_min + (alignment - 1)) & ~(alignment - 1);
> +
> +     /* Reject inconsistent args.  We have adjusted these, so this
> +      * may fail due to our internal changes even if this check
> +      * would pass for the values the user supplied. */
> +     if (req_size > address_max - address_min)
> +             goto error_out;
> +
> +     /* Walk through the list entries - first fit found is returned */
> +
> +     if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
> +             cvmx_spinlock_lock((cvmx_spinlock_t *) &
> +                                (cvmx_bootmem_desc->lock));
> +     head_addr = cvmx_bootmem_desc->head_addr;
> +     ent_addr = head_addr;
> +     while (ent_addr) {
> +             uint64_t usable_base, usable_max;
> +             uint64_t ent_size = cvmx_bootmem_phy_get_size(ent_addr);
> +
> +             if (cvmx_bootmem_phy_get_next(ent_addr)
> +                 && ent_addr > cvmx_bootmem_phy_get_next(ent_addr)) {
> +                     cvmx_dprintf
> +                         ("Internal bootmem_alloc() error: ent: 0x%llx, 
> next: 0x%llx\n",
> +                          (unsigned long long)ent_addr, (unsigned long long)
> +                          cvmx_bootmem_phy_get_next(ent_addr));
> +                     goto error_out;
> +             }
> +
> +             /* Determine if this is an entry that can satisify the request 
> */
> +             /* Check to make sure entry is large enough to satisfy request 
> */
> +             usable_base =
> +                 ALIGN_ADDR_UP(MAX(address_min, ent_addr), alignment_mask);
> +             usable_max = MIN(address_max, ent_addr + ent_size);
> +             /* We should be able to allocate block at address usable_base */
> +
> +             desired_min_addr = usable_base;
> +
> +             /* Determine if request can be satisfied from the current entry 
> */
> +             if ((((ent_addr + ent_size) > usable_base
> +                   && ent_addr < address_max))
> +                 && req_size <= usable_max - usable_base) {
> +                     /* We have found an entry that has room to satisfy the 
> request, so allocate it from this entry */
> +
> +                     /* If end CVMX_BOOTMEM_FLAG_END_ALLOC set, then 
> allocate from the end of this block
> +                      ** rather than the beginning */
> +                     if (flags & CVMX_BOOTMEM_FLAG_END_ALLOC) {
> +                             desired_min_addr = usable_max - req_size;
> +                             /* Align desired address down to required 
> alignment */
> +                             desired_min_addr &= alignment_mask;
> +                     }
> +
> +                     /* Match at start of entry */
> +                     if (desired_min_addr == ent_addr) {
> +                             if (req_size < ent_size) {
> +                                     /* big enough to create a new block 
> from top portion of block */
> +                                     new_ent_addr = ent_addr + req_size;
> +                                     cvmx_bootmem_phy_set_next(new_ent_addr,
> +                                                               
> cvmx_bootmem_phy_get_next
> +                                                               (ent_addr));
> +                                     cvmx_bootmem_phy_set_size(new_ent_addr,
> +                                                               ent_size -
> +                                                               req_size);
> +
> +                                     /* Adjust next pointer as following 
> code uses this */
> +                                     cvmx_bootmem_phy_set_next(ent_addr,
> +                                                               new_ent_addr);
> +                             }
> +
> +                             /* adjust prev ptr or head to remove this entry 
> from list */
> +                             if (prev_addr) {
> +                                     cvmx_bootmem_phy_set_next(prev_addr,
> +                                                               
> cvmx_bootmem_phy_get_next
> +                                                               (ent_addr));
> +                             } else {
> +                                     /* head of list being returned, so 
> update head ptr */
> +                                     cvmx_bootmem_desc->head_addr =
> +                                         cvmx_bootmem_phy_get_next(ent_addr);
> +                             }
> +                             if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
> +                                     cvmx_spinlock_unlock((cvmx_spinlock_t *)
> +                                                          &
> +                                                          
> (cvmx_bootmem_desc->lock));
> +                             return desired_min_addr;
> +                     }
> +
> +                     /* block returned doesn't start at beginning
> +                      * of entry, so we know that we will be
> +                      * splitting a block off the front of this
> +                      * one.  Create a new block from the
> +                      * beginning, add to list, and go to top of
> +                      * loop again.
> +                      *
> +                      * create new block from high portion of
> +                      * block, so that top block starts at desired
> +                      * addr
> +                      **/
> +                     new_ent_addr = desired_min_addr;
> +                     cvmx_bootmem_phy_set_next(new_ent_addr,
> +                                               cvmx_bootmem_phy_get_next
> +                                               (ent_addr));
> +                     cvmx_bootmem_phy_set_size(new_ent_addr,
> +                                               cvmx_bootmem_phy_get_size
> +                                               (ent_addr) -
> +                                               (desired_min_addr -
> +                                                ent_addr));
> +                     cvmx_bootmem_phy_set_size(ent_addr,
> +                                               desired_min_addr - ent_addr);
> +                     cvmx_bootmem_phy_set_next(ent_addr, new_ent_addr);
> +                     /* Loop again to handle actual alloc from new block */
> +             }
> +
> +             prev_addr = ent_addr;
> +             ent_addr = cvmx_bootmem_phy_get_next(ent_addr);
> +     }
> +error_out:
> +     /* We didn't find anything, so return error */
> +     if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
> +             cvmx_spinlock_unlock((cvmx_spinlock_t *) &
> +                                  (cvmx_bootmem_desc->lock));
> +     return -1;
> +}
> +
> +int __cvmx_bootmem_phy_free(uint64_t phy_addr, uint64_t size, uint32_t flags)
> +{
> +     uint64_t cur_addr;
> +     uint64_t prev_addr = 0; /* zero is invalid */
> +     int retval = 0;
> +
> +#ifdef DEBUG
> +     cvmx_dprintf("__cvmx_bootmem_phy_free addr: 0x%llx, size: 0x%llx\n",
> +                  (unsigned long long)phy_addr, (unsigned long long)size);
> +#endif
> +     if (cvmx_bootmem_desc->major_version > 3) {
> +             cvmx_dprintf
> +                 ("ERROR: Incompatible bootmem descriptor version: %d.%d at 
> addr: %p\n",
> +                  (int)cvmx_bootmem_desc->major_version,
> +                  (int)cvmx_bootmem_desc->minor_version, cvmx_bootmem_desc);
> +             return 0;
> +     }
> +
> +     /* 0 is not a valid size for this allocator */
> +     if (!size)
> +             return 0;
> +
> +     if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
> +             cvmx_spinlock_lock((cvmx_spinlock_t *) &
> +                                (cvmx_bootmem_desc->lock));
> +     cur_addr = cvmx_bootmem_desc->head_addr;
> +     if (cur_addr == 0 || phy_addr < cur_addr) {
> +             /* add at front of list - special case with changing head ptr */
> +             if (cur_addr && phy_addr + size > cur_addr)
> +                     goto bootmem_free_done; /* error, overlapping section */
> +             else if (phy_addr + size == cur_addr) {
> +                     /* Add to front of existing first block */
> +                     cvmx_bootmem_phy_set_next(phy_addr,
> +                                               cvmx_bootmem_phy_get_next
> +                                               (cur_addr));
> +                     cvmx_bootmem_phy_set_size(phy_addr,
> +                                               cvmx_bootmem_phy_get_size
> +                                               (cur_addr) + size);
> +                     cvmx_bootmem_desc->head_addr = phy_addr;
> +
> +             } else {
> +                     /* New block before first block */
> +                     cvmx_bootmem_phy_set_next(phy_addr, cur_addr);  /* OK 
> if cur_addr is 0 */
> +                     cvmx_bootmem_phy_set_size(phy_addr, size);
> +                     cvmx_bootmem_desc->head_addr = phy_addr;
> +             }
> +             retval = 1;
> +             goto bootmem_free_done;
> +     }
> +
> +     /* Find place in list to add block */
> +     while (cur_addr && phy_addr > cur_addr) {
> +             prev_addr = cur_addr;
> +             cur_addr = cvmx_bootmem_phy_get_next(cur_addr);
> +     }
> +
> +     if (!cur_addr) {
> +             /* We have reached the end of the list, add on to end, checking
> +              ** to see if we need to combine with last block
> +              **/
> +             if (prev_addr + cvmx_bootmem_phy_get_size(prev_addr) ==
> +                 phy_addr) {
> +                     cvmx_bootmem_phy_set_size(prev_addr,
> +                                               cvmx_bootmem_phy_get_size
> +                                               (prev_addr) + size);
> +             } else {
> +                     cvmx_bootmem_phy_set_next(prev_addr, phy_addr);
> +                     cvmx_bootmem_phy_set_size(phy_addr, size);
> +                     cvmx_bootmem_phy_set_next(phy_addr, 0);
> +             }
> +             retval = 1;
> +             goto bootmem_free_done;
> +     } else {
> +             /* insert between prev and cur nodes, checking for merge with 
> either/both */
> +
> +             if (prev_addr + cvmx_bootmem_phy_get_size(prev_addr) ==
> +                 phy_addr) {
> +                     /* Merge with previous */
> +                     cvmx_bootmem_phy_set_size(prev_addr,
> +                                               cvmx_bootmem_phy_get_size
> +                                               (prev_addr) + size);
> +                     if (phy_addr + size == cur_addr) {
> +                             /* Also merge with current */
> +                             cvmx_bootmem_phy_set_size(prev_addr,
> +                                                       
> cvmx_bootmem_phy_get_size
> +                                                       (cur_addr) +
> +                                                       
> cvmx_bootmem_phy_get_size
> +                                                       (prev_addr));
> +                             cvmx_bootmem_phy_set_next(prev_addr,
> +                                                       
> cvmx_bootmem_phy_get_next
> +                                                       (cur_addr));
> +                     }
> +                     retval = 1;
> +                     goto bootmem_free_done;
> +             } else if (phy_addr + size == cur_addr) {
> +                     /* Merge with current */
> +                     cvmx_bootmem_phy_set_size(phy_addr,
> +                                               cvmx_bootmem_phy_get_size
> +                                               (cur_addr) + size);
> +                     cvmx_bootmem_phy_set_next(phy_addr,
> +                                               cvmx_bootmem_phy_get_next
> +                                               (cur_addr));
> +                     cvmx_bootmem_phy_set_next(prev_addr, phy_addr);
> +                     retval = 1;
> +                     goto bootmem_free_done;
> +             }
> +
> +             /* It is a standalone block, add in between prev and cur */
> +             cvmx_bootmem_phy_set_size(phy_addr, size);
> +             cvmx_bootmem_phy_set_next(phy_addr, cur_addr);
> +             cvmx_bootmem_phy_set_next(prev_addr, phy_addr);
> +
> +     }
> +     retval = 1;
> +
> +bootmem_free_done:
> +     if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
> +             cvmx_spinlock_unlock((cvmx_spinlock_t *) &
> +                                  (cvmx_bootmem_desc->lock));
> +     return retval;
> +
> +}
> +
> +void cvmx_bootmem_phy_list_print(void)
> +{
> +     uint64_t addr;
> +
> +     addr = cvmx_bootmem_desc->head_addr;
> +     cvmx_dprintf
> +         ("\n\n\nPrinting bootmem block list, descriptor: %p,  head is 
> 0x%llx\n",
> +          cvmx_bootmem_desc, (unsigned long long)addr);
> +     cvmx_dprintf("Descriptor version: %d.%d\n",
> +                  (int)cvmx_bootmem_desc->major_version,
> +                  (int)cvmx_bootmem_desc->minor_version);
> +     if (cvmx_bootmem_desc->major_version > 3) {
> +             cvmx_dprintf
> +                 ("Warning: Bootmem descriptor version is newer than 
> expected\n");
> +     }
> +     if (!addr) {
> +             cvmx_dprintf("mem list is empty!\n");
> +     }
> +     while (addr) {
> +             cvmx_dprintf
> +                 ("Block address: 0x%08qx, size: 0x%08qx, next: 0x%08qx\n",
> +                  (unsigned long long)addr,
> +                  (unsigned long long)cvmx_bootmem_phy_get_size(addr),
> +                  (unsigned long long)cvmx_bootmem_phy_get_next(addr));
> +             addr = cvmx_bootmem_phy_get_next(addr);
> +     }
> +     cvmx_dprintf("\n\n");
> +
> +}
> +
> +uint64_t cvmx_bootmem_phy_available_mem(uint64_t min_block_size)
> +{
> +     uint64_t addr;
> +
> +     uint64_t available_mem = 0;
> +
> +     cvmx_spinlock_lock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock));
> +     addr = cvmx_bootmem_desc->head_addr;
> +     while (addr) {
> +             if (cvmx_bootmem_phy_get_size(addr) >= min_block_size)
> +                     available_mem += cvmx_bootmem_phy_get_size(addr);
> +             addr = cvmx_bootmem_phy_get_next(addr);
> +     }
> +     cvmx_spinlock_unlock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock));
> +     return available_mem;
> +
> +}
> +
> +cvmx_bootmem_named_block_desc_t *cvmx_bootmem_phy_named_block_find(char 
> *name,
> +                                                                uint32_t
> +                                                                flags)
> +{
> +     unsigned int i;
> +     cvmx_bootmem_named_block_desc_t *named_block_array_ptr;
> +
> +#ifdef DEBUG
> +     cvmx_dprintf("cvmx_bootmem_phy_named_block_find: %s\n", name);
> +#endif
> +     /* Lock the structure to make sure that it is not being
> +      * changed while we are examining it.
> +      */
> +     if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
> +             cvmx_spinlock_lock((cvmx_spinlock_t *) &
> +                                (cvmx_bootmem_desc->lock));
> +
> +#if !defined(CONFIG_OCTEON_U_BOOT)
> +     /* Use XKPHYS for 64 bit linux */
> +     named_block_array_ptr = (cvmx_bootmem_named_block_desc_t *)
> +         cvmx_phys_to_ptr(cvmx_bootmem_desc->named_block_array_addr);
> +#else
> +     /* Simple executive case. (and u-boot) This could be in the
> +      * low 1 meg of memory that is not 1-1 mapped, so we need use
> +      * XKPHYS/KSEG0 addressing for it */
> +     named_block_array_ptr =
> +         CASTPTR(cvmx_bootmem_named_block_desc_t,
> +                 CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0,
> +                                cvmx_bootmem_desc->named_block_array_addr));
> +#endif
> +
> +#ifdef DEBUG
> +     cvmx_dprintf
> +         ("cvmx_bootmem_phy_named_block_find: named_block_array_ptr: %p\n",
> +          named_block_array_ptr);
> +#endif
> +     if (cvmx_bootmem_desc->major_version == 3) {
> +             for (i = 0; i < cvmx_bootmem_desc->named_block_num_blocks; i++) 
> {
> +                     if ((name && named_block_array_ptr[i].size
> +                          && !strncmp(name, named_block_array_ptr[i].name,
> +                                      cvmx_bootmem_desc->named_block_name_len
> +                                      - 1))
> +                         || (!name && !named_block_array_ptr[i].size)) {
> +                             if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
> +                                     cvmx_spinlock_unlock((cvmx_spinlock_t *)
> +                                                          &
> +                                                          
> (cvmx_bootmem_desc->lock));
> +
> +                             return &(named_block_array_ptr[i]);
> +                     }
> +             }
> +     } else {
> +             cvmx_dprintf
> +                 ("ERROR: Incompatible bootmem descriptor version: %d.%d at 
> addr: %p\n",
> +                  (int)cvmx_bootmem_desc->major_version,
> +                  (int)cvmx_bootmem_desc->minor_version, cvmx_bootmem_desc);
> +     }
> +     if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
> +             cvmx_spinlock_unlock((cvmx_spinlock_t *) &
> +                                  (cvmx_bootmem_desc->lock));
> +
> +     return NULL;
> +}
> +
> +int cvmx_bootmem_phy_named_block_free(char *name, uint32_t flags)
> +{
> +     cvmx_bootmem_named_block_desc_t *named_block_ptr;
> +
> +     if (cvmx_bootmem_desc->major_version != 3) {
> +             cvmx_dprintf
> +                 ("ERROR: Incompatible bootmem descriptor version: %d.%d at 
> addr: %p\n",
> +                  (int)cvmx_bootmem_desc->major_version,
> +                  (int)cvmx_bootmem_desc->minor_version, cvmx_bootmem_desc);
> +             return 0;
> +     }
> +#ifdef DEBUG
> +     cvmx_dprintf("cvmx_bootmem_phy_named_block_free: %s\n", name);
> +#endif
> +
> +     /* Take lock here, as name lookup/block free/name free need to be 
> atomic */
> +     cvmx_spinlock_lock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock));
> +
> +     named_block_ptr =
> +         cvmx_bootmem_phy_named_block_find(name,
> +                                           CVMX_BOOTMEM_FLAG_NO_LOCKING);
> +     if (named_block_ptr) {
> +#ifdef DEBUG
> +             cvmx_dprintf
> +                 ("cvmx_bootmem_phy_named_block_free: %s, base: 0x%llx, 
> size: 0x%llx\n",
> +                  name, (unsigned long long)named_block_ptr->base_addr,
> +                  (unsigned long long)named_block_ptr->size);
> +#endif
> +             __cvmx_bootmem_phy_free(named_block_ptr->base_addr,
> +                                     named_block_ptr->size,
> +                                     CVMX_BOOTMEM_FLAG_NO_LOCKING);
> +             named_block_ptr->size = 0;
> +             /* Set size to zero to indicate block not used. */
> +     }
> +
> +     cvmx_spinlock_unlock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock));
> +
> +     return named_block_ptr != NULL; /* 0 on failure, 1 on success */
> +}
> +
> +int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr,
> +                                        uint64_t max_addr,
> +                                        uint64_t alignment, char *name,
> +                                        uint32_t flags)
> +{
> +     int64_t addr_allocated;
> +     cvmx_bootmem_named_block_desc_t *named_block_desc_ptr;
> +
> +#ifdef DEBUG
> +     cvmx_dprintf
> +         ("cvmx_bootmem_phy_named_block_alloc: size: 0x%llx, min: 0x%llx, 
> max: 0x%llx, align: 0x%llx, name: %s\n",
> +          (unsigned long long)size, (unsigned long long)min_addr,
> +          (unsigned long long)max_addr, (unsigned long long)alignment, name);
> +#endif
> +     if (cvmx_bootmem_desc->major_version != 3) {
> +             cvmx_dprintf
> +                 ("ERROR: Incompatible bootmem descriptor version: %d.%d at 
> addr: %p\n",
> +                  (int)cvmx_bootmem_desc->major_version,
> +                  (int)cvmx_bootmem_desc->minor_version, cvmx_bootmem_desc);
> +             return -1;
> +     }
> +
> +     /* Take lock here, as name lookup/block alloc/name add need to be 
> atomic */
> +
> +     if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
> +             cvmx_spinlock_lock((cvmx_spinlock_t *) &
> +                                (cvmx_bootmem_desc->lock));
> +
> +     /* Get pointer to first available named block descriptor */
> +     named_block_desc_ptr =
> +         cvmx_bootmem_phy_named_block_find(NULL,
> +                                           flags |
> +                                           CVMX_BOOTMEM_FLAG_NO_LOCKING);
> +
> +     /* Check to see if name already in use, return error if name
> +      ** not available or no more room for blocks.
> +      */
> +     if (cvmx_bootmem_phy_named_block_find
> +         (name, flags | CVMX_BOOTMEM_FLAG_NO_LOCKING)
> +         || !named_block_desc_ptr) {
> +             if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
> +                     cvmx_spinlock_unlock((cvmx_spinlock_t *) &
> +                                          (cvmx_bootmem_desc->lock));
> +             return -1;
> +     }
> +
> +     /* Round size up to mult of minimum alignment bytes
> +      ** We need the actual size allocated to allow for blocks to be 
> coallesced
> +      ** when they are freed.  The alloc routine does the same rounding up
> +      ** on all allocations. */
> +     size =
> +         (size +
> +          (CVMX_BOOTMEM_ALIGNMENT_SIZE -
> +           1)) & ~(CVMX_BOOTMEM_ALIGNMENT_SIZE - 1);
> +
> +     addr_allocated =
> +         cvmx_bootmem_phy_alloc(size, min_addr, max_addr, alignment,
> +                                flags | CVMX_BOOTMEM_FLAG_NO_LOCKING);
> +     if (addr_allocated >= 0) {
> +             named_block_desc_ptr->base_addr = addr_allocated;
> +             named_block_desc_ptr->size = size;
> +             strncpy(named_block_desc_ptr->name, name,
> +                     cvmx_bootmem_desc->named_block_name_len);
> +             named_block_desc_ptr->
> +                 name[cvmx_bootmem_desc->named_block_name_len - 1] = 0;
> +     }
> +
> +     if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
> +             cvmx_spinlock_unlock((cvmx_spinlock_t *) &
> +                                  (cvmx_bootmem_desc->lock));
> +
> +     return addr_allocated;
> +}
> +
> +void cvmx_bootmem_phy_named_block_print(void)
> +{
> +     unsigned int i;
> +     int printed = 0;
> +
> +#if !defined(CONFIG_OCTEON_U_BOOT)
> +     /* Use XKPHYS for 64 bit linux */
> +     cvmx_bootmem_named_block_desc_t *named_block_array_ptr =
> +         (cvmx_bootmem_named_block_desc_t *)
> +         cvmx_phys_to_ptr(cvmx_bootmem_desc->named_block_array_addr);
> +#else
> +     /* Simple executive case. (and u-boot)
> +      ** This could be in the low 1 meg of memory that is not 1-1 mapped, so 
> we need use XKPHYS/KSEG0 addressing for it */
> +     cvmx_bootmem_named_block_desc_t *named_block_array_ptr =
> +         CASTPTR(cvmx_bootmem_named_block_desc_t,
> +                 CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0,
> +                                cvmx_bootmem_desc->named_block_array_addr));
> +#endif
> +#ifdef DEBUG
> +     cvmx_dprintf("cvmx_bootmem_phy_named_block_print, desc addr: %p\n",
> +                  cvmx_bootmem_desc);
> +#endif
> +     if (cvmx_bootmem_desc->major_version != 3) {
> +             cvmx_dprintf
> +                 ("ERROR: Incompatible bootmem descriptor version: %d.%d at 
> addr: %p\n",
> +                  (int)cvmx_bootmem_desc->major_version,
> +                  (int)cvmx_bootmem_desc->minor_version, cvmx_bootmem_desc);
> +             return;
> +     }
> +     cvmx_dprintf("List of currently allocated named bootmem blocks:\n");
> +     for (i = 0; i < cvmx_bootmem_desc->named_block_num_blocks; i++) {
> +             if (named_block_array_ptr[i].size) {
> +                     printed++;
> +                     cvmx_dprintf
> +                         ("Name: %s, address: 0x%08qx, size: 0x%08qx, index: 
> %d\n",
> +                          named_block_array_ptr[i].name,
> +                          (unsigned long long)
> +                          named_block_array_ptr[i].base_addr,
> +                          (unsigned long long)named_block_array_ptr[i].size,
> +                          i);
> +
> +             }
> +     }
> +     if (!printed) {
> +             cvmx_dprintf("No named bootmem blocks exist.\n");
> +     }
> +
> +}
> +
> +/* Real physical addresses of memory regions */
> +#define OCTEON_DDR0_BASE    (0x0ULL)
> +#define OCTEON_DDR0_SIZE    (0x010000000ULL)
> +#define OCTEON_DDR1_BASE    (0x410000000ULL)
> +#define OCTEON_DDR1_SIZE    (0x010000000ULL)
> +#define OCTEON_DDR2_BASE    (0x020000000ULL)
> +#define OCTEON_DDR2_SIZE    (0x3e0000000ULL)
> +#define OCTEON_MAX_PHY_MEM_SIZE (16*1024*1024*1024ULL)
> +int64_t cvmx_bootmem_phy_mem_list_init(uint64_t mem_size,
> +                                    uint32_t low_reserved_bytes,
> +                                    cvmx_bootmem_desc_t *desc_buffer)
> +{
> +     uint64_t cur_block_addr;
> +     int64_t addr;
> +
> +#ifdef DEBUG
> +     cvmx_dprintf
> +         ("cvmx_bootmem_phy_mem_list_init (arg desc ptr: %p, 
> cvmx_bootmem_desc: %p)\n",
> +          desc_buffer, cvmx_bootmem_desc);
> +#endif
> +
> +     /* Descriptor buffer needs to be in 32 bit addressable space to be 
> compatible with
> +      ** 32 bit applications */
> +     if (!desc_buffer) {
> +             cvmx_dprintf
> +                 ("ERROR: no memory for cvmx_bootmem descriptor provided\n");
> +             return 0;
> +     }
> +
> +     if (mem_size > OCTEON_MAX_PHY_MEM_SIZE) {
> +             mem_size = OCTEON_MAX_PHY_MEM_SIZE;
> +             cvmx_dprintf
> +                 ("ERROR: requested memory size too large, truncating to 
> maximum size\n");
> +     }
> +
> +     if (cvmx_bootmem_desc)
> +             return 1;
> +
> +     /* Initialize cvmx pointer to descriptor */
> +     cvmx_bootmem_init(desc_buffer);
> +
> +     /* Set up global pointer to start of list, exclude low 64k for 
> exception vectors, space for global descriptor */
> +     memset(cvmx_bootmem_desc, 0x0, sizeof(cvmx_bootmem_desc_t));
> +     /* Set version of bootmem descriptor */
> +     cvmx_bootmem_desc->major_version = CVMX_BOOTMEM_DESC_MAJ_VER;
> +     cvmx_bootmem_desc->minor_version = CVMX_BOOTMEM_DESC_MIN_VER;
> +
> +     cur_block_addr = cvmx_bootmem_desc->head_addr =
> +         (OCTEON_DDR0_BASE + low_reserved_bytes);
> +
> +     cvmx_bootmem_desc->head_addr = 0;
> +
> +     if (mem_size <= OCTEON_DDR0_SIZE) {
> +             __cvmx_bootmem_phy_free(cur_block_addr,
> +                                     mem_size - low_reserved_bytes, 0);
> +             goto frees_done;
> +     }
> +
> +     __cvmx_bootmem_phy_free(cur_block_addr,
> +                             OCTEON_DDR0_SIZE - low_reserved_bytes, 0);
> +
> +     mem_size -= OCTEON_DDR0_SIZE;
> +
> +     /* Add DDR2 block next if present */
> +     if (mem_size > OCTEON_DDR1_SIZE) {
> +             __cvmx_bootmem_phy_free(OCTEON_DDR1_BASE, OCTEON_DDR1_SIZE, 0);
> +             __cvmx_bootmem_phy_free(OCTEON_DDR2_BASE,
> +                                     mem_size - OCTEON_DDR1_SIZE, 0);
> +     } else {
> +             __cvmx_bootmem_phy_free(OCTEON_DDR1_BASE, mem_size, 0);
> +
> +     }
> +frees_done:
> +
> +     /* Initialize the named block structure */
> +     cvmx_bootmem_desc->named_block_name_len = CVMX_BOOTMEM_NAME_LEN;
> +     cvmx_bootmem_desc->named_block_num_blocks =
> +         CVMX_BOOTMEM_NUM_NAMED_BLOCKS;
> +     cvmx_bootmem_desc->named_block_array_addr = 0;
> +
> +     /* Allocate this near the top of the low 256 MBytes of memory */
> +     addr =
> +         cvmx_bootmem_phy_alloc(CVMX_BOOTMEM_NUM_NAMED_BLOCKS *
> +                                sizeof(cvmx_bootmem_named_block_desc_t), 0,
> +                                0x10000000, 0, CVMX_BOOTMEM_FLAG_END_ALLOC);
> +     if (addr >= 0)
> +             cvmx_bootmem_desc->named_block_array_addr = addr;
> +
> +#ifdef DEBUG
> +     cvmx_dprintf
> +         ("cvmx_bootmem_phy_mem_list_init: named_block_array_addr: 
> 0x%llx)\n",
> +          (unsigned long long)cvmx_bootmem_desc->named_block_array_addr);
> +#endif
> +     if (!cvmx_bootmem_desc->named_block_array_addr) {
> +             cvmx_dprintf
> +                 ("FATAL ERROR: unable to allocate memory for bootmem 
> descriptor!\n");
> +             return 0;
> +     }
> +     memset((void *)(unsigned long)cvmx_bootmem_desc->named_block_array_addr,
> +            0x0,
> +            CVMX_BOOTMEM_NUM_NAMED_BLOCKS *
> +            sizeof(cvmx_bootmem_named_block_desc_t));
> +
> +     return 1;
> +}
> +
> +void cvmx_bootmem_lock(void)
> +{
> +     cvmx_spinlock_lock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock));
> +}
> +
> +void cvmx_bootmem_unlock(void)
> +{
> +     cvmx_spinlock_unlock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock));
> +}
> +
> +void *__cvmx_bootmem_internal_get_desc_ptr(void)
> +{
> +     return cvmx_bootmem_desc;
> +}
> diff --git a/arch/mips/cavium-octeon/executive/cvmx-bootmem.h 
> b/arch/mips/cavium-octeon/executive/cvmx-bootmem.h
> new file mode 100644
> index 0000000..71cf611
> --- /dev/null
> +++ b/arch/mips/cavium-octeon/executive/cvmx-bootmem.h
> @@ -0,0 +1,403 @@
> +/***********************license start***************
> + * Author: Cavium Networks
> + *
> + * Contact: support@caviumnetworks.com
> + * This file is part of the OCTEON SDK
> + *
> + * Copyright (c) 2003-2008 Cavium Networks
> + *
> + * This file is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, Version 2, as 
> published by
> + * the Free Software Foundation.
> + *
> + * This file is distributed in the hope that it will be useful,
> + * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 
> NONINFRINGEMENT.
> + * See the GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this file; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + * or visit http://www.gnu.org/licenses/.
> + *
> + * This file may also be available under a different license from Cavium.
> + * Contact Cavium Networks for more information
> + ***********************license end**************************************/
> +
> +/**
> + * @file
> + * Simple allocate only memory allocator.  Used to allocate memory at 
> application
> + * start time.
> + *
> + *
> + */
> +
> +#ifndef __CVMX_BOOTMEM_H__
> +#define __CVMX_BOOTMEM_H__
> +
> +#define CVMX_BOOTMEM_NAME_LEN 128    /* Must be multiple of 8, changing 
> breaks ABI */
> +#define CVMX_BOOTMEM_NUM_NAMED_BLOCKS 64     /* Can change without breaking 
> ABI */
> +#define CVMX_BOOTMEM_ALIGNMENT_SIZE     (16ull)      /* minimum alignment of 
> bootmem alloced blocks */
> +
> +/* Flags for cvmx_bootmem_phy_mem* functions */
> +#define CVMX_BOOTMEM_FLAG_END_ALLOC    (1 << 0)      /* Allocate from end of 
> block instead of beginning */
> +#define CVMX_BOOTMEM_FLAG_NO_LOCKING   (1 << 1)      /* Don't do any 
> locking. */
> +
> +/* First bytes of each free physical block of memory contain this structure,
> + * which is used to maintain the free memory list.  Since the bootloader is
> + * only 32 bits, there is a union providing 64 and 32 bit versions.  The
> + * application init code converts addresses to 64 bit addresses before the
> + * application starts.
> + */
> +typedef struct {
> +     /* Note: these are referenced from assembly routines in the bootloader, 
> so this structure
> +      ** should not be changed without changing those routines as well. */
> +     uint64_t next_block_addr;
> +     uint64_t size;
> +
> +} cvmx_bootmem_block_header_t;
> +
> +/* Structure for named memory blocks
> +** Number of descriptors
> +** available can be changed without affecting compatiblity,
> +** but name length changes require a bump in the bootmem
> +** descriptor version
> +** Note: This structure must be naturally 64 bit aligned, as a single
> +** memory image will be used by both 32 and 64 bit programs.
> +*/
> +typedef struct {
> +     uint64_t base_addr;
> +                         /**< Base address of named block */
> +     uint64_t size;
> +                         /**< Size actually allocated for named block (may 
> differ from requested) */
> +     char name[CVMX_BOOTMEM_NAME_LEN];
> +                                     /**< name of named block */
> +} cvmx_bootmem_named_block_desc_t;
> +
> +/* Current descriptor versions */
> +#define CVMX_BOOTMEM_DESC_MAJ_VER   3        /* CVMX bootmem descriptor 
> major version */
> +#define CVMX_BOOTMEM_DESC_MIN_VER   0        /* CVMX bootmem descriptor 
> minor version */
> +
> +/* First three members of cvmx_bootmem_desc_t are left in original
> +** positions for backwards compatibility.
> +*/
> +typedef struct {
> +     uint32_t lock;
> +                         /**< spinlock to control access to list */
> +     uint32_t flags;
> +                         /**< flags for indicating various conditions */
> +     uint64_t head_addr;
> +
> +     uint32_t major_version;
> +                             /**< incremented changed when incompatible 
> changes made */
> +     uint32_t minor_version;
> +                             /**< incremented changed when compatible 
> changes made, reset to zero when major incremented */
> +     uint64_t app_data_addr;
> +     uint64_t app_data_size;
> +
> +     uint32_t named_block_num_blocks;
> +                                      /**< number of elements in named 
> blocks array */
> +     uint32_t named_block_name_len;
> +                                      /**< length of name array in bootmem 
> blocks */
> +     uint64_t named_block_array_addr;
> +                                      /**< address of named memory block 
> descriptors */
> +
> +} cvmx_bootmem_desc_t;
> +
> +/**
> + * Initialize the boot alloc memory structures. This is
> + * normally called inside of cvmx_user_app_init()
> + *
> + * @param mem_desc_ptr       Address of the free memory list
> + * @return
> + */
> +extern int cvmx_bootmem_init(void *mem_desc_ptr);
> +
> +/**
> + * Allocate a block of memory from the free list that was passed
> + * to the application by the bootloader.
> + * This is an allocate-only algorithm, so freeing memory is not possible.
> + *
> + * @param size      Size in bytes of block to allocate
> + * @param alignment Alignment required - must be power of 2
> + *
> + * @return pointer to block of memory, NULL on error
> + */
> +extern void *cvmx_bootmem_alloc(uint64_t size, uint64_t alignment);
> +
> +/**
> + * Allocate a block of memory from the free list that was
> + * passed to the application by the bootloader at a specific
> + * address. This is an allocate-only algorithm, so
> + * freeing memory is not possible. Allocation will fail if
> + * memory cannot be allocated at the specified address.
> + *
> + * @param size      Size in bytes of block to allocate
> + * @param address   Physical address to allocate memory at.  If this memory 
> is not
> + *                  available, the allocation fails.
> + * @param alignment Alignment required - must be power of 2
> + * @return pointer to block of memory, NULL on error
> + */
> +extern void *cvmx_bootmem_alloc_address(uint64_t size, uint64_t address,
> +                                     uint64_t alignment);
> +
> +/**
> + * Allocate a block of memory from the free list that was
> + * passed to the application by the bootloader within a specified
> + * address range. This is an allocate-only algorithm, so
> + * freeing memory is not possible. Allocation will fail if
> + * memory cannot be allocated in the requested range.
> + *
> + * @param size      Size in bytes of block to allocate
> + * @param min_addr  defines the minimum address of the range
> + * @param max_addr  defines the maximum address of the range
> + * @param alignment Alignment required - must be power of 2
> + * @return pointer to block of memory, NULL on error
> + */
> +extern void *cvmx_bootmem_alloc_range(uint64_t size, uint64_t alignment,
> +                                   uint64_t min_addr, uint64_t max_addr);
> +
> +/**
> + * Allocate a block of memory from the free list that was passed
> + * to the application by the bootloader, and assign it a name in the
> + * global named block table.  (part of the cvmx_bootmem_descriptor_t 
> structure)
> + * Named blocks can later be freed.
> + *
> + * @param size      Size in bytes of block to allocate
> + * @param alignment Alignment required - must be power of 2
> + * @param name      name of block - must be less than CVMX_BOOTMEM_NAME_LEN 
> bytes
> + *
> + * @return pointer to block of memory, NULL on error
> + */
> +extern void *cvmx_bootmem_alloc_named(uint64_t size, uint64_t alignment,
> +                                   char *name);
> +
> +/**
> + * Allocate a block of memory from the free list that was passed
> + * to the application by the bootloader, and assign it a name in the
> + * global named block table.  (part of the cvmx_bootmem_descriptor_t 
> structure)
> + * Named blocks can later be freed.
> + *
> + * @param size      Size in bytes of block to allocate
> + * @param address   Physical address to allocate memory at.  If this memory 
> is not
> + *                  available, the allocation fails.
> + * @param name      name of block - must be less than CVMX_BOOTMEM_NAME_LEN 
> bytes
> + *
> + * @return pointer to block of memory, NULL on error
> + */
> +extern void *cvmx_bootmem_alloc_named_address(uint64_t size,
> +                                           uint64_t address, char *name);
> +
> +/**
> + * Allocate a block of memory from a specific range of the free list that 
> was passed
> + * to the application by the bootloader, and assign it a name in the
> + * global named block table.  (part of the cvmx_bootmem_descriptor_t 
> structure)
> + * Named blocks can later be freed.
> + * If request cannot be satisfied within the address range specified, NULL 
> is returned
> + *
> + * @param size      Size in bytes of block to allocate
> + * @param min_addr  minimum address of range
> + * @param max_addr  maximum address of range
> + * @param align  Alignment of memory to be allocated. (must be a power of 2)
> + * @param name      name of block - must be less than CVMX_BOOTMEM_NAME_LEN 
> bytes
> + *
> + * @return pointer to block of memory, NULL on error
> + */
> +extern void *cvmx_bootmem_alloc_named_range(uint64_t size,
> +                                         uint64_t min_addr,
> +                                         uint64_t max_addr,
> +                                         uint64_t