diff options
author | Ruiling Song <ruiling.song@intel.com> | 2014-07-30 13:59:29 +0800 |
---|---|---|
committer | Zhigang Gong <zhigang.gong@intel.com> | 2014-07-30 15:23:43 +0800 |
commit | e16f34c027b3e7a19355c91d728632d82995b2b0 (patch) | |
tree | 188e10aea38d79b2c8fee9e2c91b569bcf383880 /backend/src/ir | |
parent | 778f56447172c737eceb8aaccca3d2801f242152 (diff) |
GBE: Refine bti usage in backend & runtime.
Previously, we simply map 2G surface for memory access,
which has obvious security issue, user can easily read/write graphics
memory that does not belong to him. To prevent such kind of behaviour,
We bind each surface to a dedicated bti. HW provides automatic
bounds check. For out-of-bound write, it will be ignored. And for read
out-of-bound, hardware will simply return zero value.
The idea behind the patch is for a load/store instruction, it will search
through the LLVM use-def chain until finding out where the address
comes from. Then the bti is saved in ir::Instruction and used for
the later code generation. And for mixed pointer case, a load/store
will access more than one bti.
To simplify some code, '0' is reserved for constant address space,
'1' is reserved for private address space. Other btis are assigned
automatically by backend.
Signed-off-by: Ruiling Song <ruiling.song@intel.com>
Reviewed-by: Zhigang Gong <zhigang.gong@linux.intel.com>
Diffstat (limited to 'backend/src/ir')
-rw-r--r-- | backend/src/ir/context.cpp | 4 | ||||
-rw-r--r-- | backend/src/ir/context.hpp | 10 | ||||
-rw-r--r-- | backend/src/ir/function.hpp | 5 | ||||
-rw-r--r-- | backend/src/ir/image.cpp | 9 | ||||
-rw-r--r-- | backend/src/ir/image.hpp | 2 | ||||
-rw-r--r-- | backend/src/ir/instruction.cpp | 39 | ||||
-rw-r--r-- | backend/src/ir/instruction.hpp | 18 |
7 files changed, 61 insertions, 26 deletions
diff --git a/backend/src/ir/context.cpp b/backend/src/ir/context.cpp index bfbe8257..1528a8d8 100644 --- a/backend/src/ir/context.cpp +++ b/backend/src/ir/context.cpp @@ -108,10 +108,10 @@ namespace ir { } void Context::input(const std::string &name, FunctionArgument::Type type, Register reg, - FunctionArgument::InfoFromLLVM& info, uint32_t elementSize, uint32_t align) { + FunctionArgument::InfoFromLLVM& info, uint32_t elementSize, uint32_t align, unsigned char bti) { GBE_ASSERTM(fn != NULL, "No function currently defined"); GBE_ASSERTM(reg < fn->file.regNum(), "Out-of-bound register"); - FunctionArgument *arg = GBE_NEW(FunctionArgument, type, reg, elementSize, name, align, info); + FunctionArgument *arg = GBE_NEW(FunctionArgument, type, reg, elementSize, name, align, info, bti); fn->args.push_back(arg); } diff --git a/backend/src/ir/context.hpp b/backend/src/ir/context.hpp index 27ff4e9a..8718a868 100644 --- a/backend/src/ir/context.hpp +++ b/backend/src/ir/context.hpp @@ -110,7 +110,7 @@ namespace ir { LabelIndex label(void); /*! Append a new input register for the function */ void input(const std::string &name, FunctionArgument::Type type, Register reg, - FunctionArgument::InfoFromLLVM& info, uint32_t elemSz = 0u, uint32_t align = 0); + FunctionArgument::InfoFromLLVM& info, uint32_t elemSz = 0u, uint32_t align = 0, uint8_t bti = 0); /*! Append a new output register for the function */ void output(Register reg); /*! Get the immediate value */ @@ -163,22 +163,22 @@ namespace ir { /*! LOAD with the destinations directly specified */ template <typename... Args> - void LOAD(Type type, Register offset, AddressSpace space, bool dwAligned, Args...values) + void LOAD(Type type, Register offset, AddressSpace space, bool dwAligned, BTI bti, Args...values) { const Tuple index = this->tuple(values...); const uint16_t valueNum = std::tuple_size<std::tuple<Args...>>::value; GBE_ASSERT(valueNum > 0); - this->LOAD(type, index, offset, space, valueNum, dwAligned); + this->LOAD(type, index, offset, space, valueNum, dwAligned, bti); } /*! STORE with the sources directly specified */ template <typename... Args> - void STORE(Type type, Register offset, AddressSpace space, bool dwAligned, Args...values) + void STORE(Type type, Register offset, AddressSpace space, bool dwAligned, BTI bti, Args...values) { const Tuple index = this->tuple(values...); const uint16_t valueNum = std::tuple_size<std::tuple<Args...>>::value; GBE_ASSERT(valueNum > 0); - this->STORE(type, index, offset, space, valueNum, dwAligned); + this->STORE(type, index, offset, space, valueNum, dwAligned, bti); } protected: diff --git a/backend/src/ir/function.hpp b/backend/src/ir/function.hpp index 2710b17a..deb7552e 100644 --- a/backend/src/ir/function.hpp +++ b/backend/src/ir/function.hpp @@ -176,8 +176,8 @@ namespace ir { }; /*! Create a function input argument */ - INLINE FunctionArgument(Type type, Register reg, uint32_t size, const std::string &name, uint32_t align, InfoFromLLVM& info) : - type(type), reg(reg), size(size), align(align), name(name), info(info) { } + INLINE FunctionArgument(Type type, Register reg, uint32_t size, const std::string &name, uint32_t align, InfoFromLLVM& info, uint8_t bti) : + type(type), reg(reg), size(size), align(align), name(name), info(info), bti(bti) { } Type type; //!< Gives the type of argument we have Register reg; //!< Holds the argument @@ -185,6 +185,7 @@ namespace ir { uint32_t align; //!< address alignment for the argument const std::string name; //!< Holds the function name for IR output InfoFromLLVM info; //!< Holds the llvm passed info + uint8_t bti; //!< binding table index GBE_STRUCT(FunctionArgument); // Use custom allocator }; diff --git a/backend/src/ir/image.cpp b/backend/src/ir/image.cpp index ee80a3d1..a9b1563b 100644 --- a/backend/src/ir/image.cpp +++ b/backend/src/ir/image.cpp @@ -94,8 +94,9 @@ namespace ir { } void ImageSet::getData(struct ImageInfo *imageInfos) const { + int id = 0; for(auto &it : regMap) - imageInfos[it.second->idx - gbe_get_image_base_index()] = *it.second; + imageInfos[id++] = *it.second; } ImageSet::~ImageSet() { @@ -186,7 +187,7 @@ namespace ir { IN_UPDATE_SZ(img_info->channelOrderSlot); IN_UPDATE_SZ(img_info->dimOrderSlot); - indexMap.insert(std::make_pair(index, img_info)); + indexMap.insert(std::make_pair(img_info->idx, img_info)); } IN_UPDATE_SZ(magic); @@ -252,7 +253,7 @@ namespace ir { return reg; } - void ImageSet::append(Register imageReg, Context *ctx) + void ImageSet::append(Register imageReg, Context *ctx, uint8_t bti) { ir::FunctionArgument *arg = ctx->getFunction().getArg(imageReg); GBE_ASSERTM(arg && arg->type == ir::FunctionArgument::IMAGE, "Append an invalid reg to image set."); @@ -261,7 +262,7 @@ namespace ir { int32_t id = ctx->getFunction().getArgID(arg); struct ImageInfo *imageInfo = GBE_NEW(struct ImageInfo); imageInfo->arg_idx = id; - imageInfo->idx = regMap.size() + gbe_get_image_base_index(); + imageInfo->idx = bti; imageInfo->wSlot = -1; imageInfo->hSlot = -1; imageInfo->depthSlot = -1; diff --git a/backend/src/ir/image.hpp b/backend/src/ir/image.hpp index 82fee561..b31c7da5 100644 --- a/backend/src/ir/image.hpp +++ b/backend/src/ir/image.hpp @@ -44,7 +44,7 @@ namespace ir { { public: /*! Append an image argument. */ - void append(Register imageReg, Context *ctx); + void append(Register imageReg, Context *ctx, uint8_t bti); /*! Append an image info slot. */ void appendInfo(ImageInfoKey key, uint32_t offset); /*! Append an image info register. */ diff --git a/backend/src/ir/instruction.cpp b/backend/src/ir/instruction.cpp index 30068935..23848d3e 100644 --- a/backend/src/ir/instruction.cpp +++ b/backend/src/ir/instruction.cpp @@ -314,6 +314,7 @@ namespace ir { AtomicInstruction(AtomicOps atomicOp, Register dst, AddressSpace addrSpace, + BTI bti, Tuple src) { this->opcode = OP_ATOMIC; @@ -321,6 +322,7 @@ namespace ir { this->dst[0] = dst; this->src = src; this->addrSpace = addrSpace; + this->bti = bti; srcNum = 2; if((atomicOp == ATOMIC_OP_INC) || (atomicOp == ATOMIC_OP_DEC)) @@ -329,12 +331,14 @@ namespace ir { srcNum = 3; } INLINE AddressSpace getAddressSpace(void) const { return this->addrSpace; } + INLINE BTI getBTI(void) const { return bti; } INLINE AtomicOps getAtomicOpcode(void) const { return this->atomicOp; } INLINE bool wellFormed(const Function &fn, std::string &whyNot) const; INLINE void out(std::ostream &out, const Function &fn) const; Register dst[1]; Tuple src; AddressSpace addrSpace; //!< Address space + BTI bti; //!< bti uint8_t srcNum:2; //!<Source Number AtomicOps atomicOp:6; //!<Source Number }; @@ -400,7 +404,8 @@ namespace ir { Register offset, AddressSpace addrSpace, uint32_t valueNum, - bool dwAligned) + bool dwAligned, + BTI bti) { GBE_ASSERT(valueNum < 128); this->opcode = OP_LOAD; @@ -410,6 +415,7 @@ namespace ir { this->addrSpace = addrSpace; this->valueNum = valueNum; this->dwAligned = dwAligned ? 1 : 0; + this->bti = bti; } INLINE Register getDst(const Function &fn, uint32_t ID) const { GBE_ASSERTM(ID < valueNum, "Out-of-bound source register"); @@ -423,6 +429,7 @@ namespace ir { INLINE Type getValueType(void) const { return type; } INLINE uint32_t getValueNum(void) const { return valueNum; } INLINE AddressSpace getAddressSpace(void) const { return addrSpace; } + INLINE BTI getBTI(void) const { return bti; } INLINE bool wellFormed(const Function &fn, std::string &why) const; INLINE void out(std::ostream &out, const Function &fn) const; INLINE bool isAligned(void) const { return !!dwAligned; } @@ -431,6 +438,7 @@ namespace ir { Register offset; //!< Alias to make it similar to store Tuple values; //!< Values to load AddressSpace addrSpace; //!< Where to load + BTI bti; uint8_t valueNum:7; //!< Number of values to load uint8_t dwAligned:1; //!< DWORD aligned is what matters with GEN }; @@ -444,7 +452,8 @@ namespace ir { Register offset, AddressSpace addrSpace, uint32_t valueNum, - bool dwAligned) + bool dwAligned, + BTI bti) { GBE_ASSERT(valueNum < 255); this->opcode = OP_STORE; @@ -454,6 +463,7 @@ namespace ir { this->addrSpace = addrSpace; this->valueNum = valueNum; this->dwAligned = dwAligned ? 1 : 0; + this->bti = bti; } INLINE Register getSrc(const Function &fn, uint32_t ID) const { GBE_ASSERTM(ID < valueNum + 1u, "Out-of-bound source register for store"); @@ -473,6 +483,7 @@ namespace ir { INLINE uint32_t getValueNum(void) const { return valueNum; } INLINE Type getValueType(void) const { return type; } INLINE AddressSpace getAddressSpace(void) const { return addrSpace; } + INLINE BTI getBTI(void) const { return bti; } INLINE bool wellFormed(const Function &fn, std::string &why) const; INLINE void out(std::ostream &out, const Function &fn) const; INLINE bool isAligned(void) const { return !!dwAligned; } @@ -480,6 +491,7 @@ namespace ir { Register offset; //!< First source is the offset where to store Tuple values; //!< Values to store AddressSpace addrSpace; //!< Where to store + BTI bti; //!< Which btis need access uint8_t valueNum:7; //!< Number of values to store uint8_t dwAligned:1; //!< DWORD aligned is what matters with GEN Register dst[0]; //!< No destination @@ -1069,6 +1081,9 @@ namespace ir { out << " {" << "%" << this->getSrc(fn, 0) << "}"; for (uint32_t i = 1; i < srcNum; ++i) out << " %" << this->getSrc(fn, i); + out << " bti"; + for (uint32_t i = 0; i < bti.count; ++i) + out << ": " << (int)bti.bti[i]; } @@ -1103,6 +1118,9 @@ namespace ir { out << "%" << this->getDst(fn, i) << (i != (valueNum-1u) ? " " : ""); out << "}"; out << " %" << this->getSrc(fn, 0); + out << " bti"; + for (uint32_t i = 0; i < bti.count; ++i) + out << ": " << (int)bti.bti[i]; } INLINE void StoreInstruction::out(std::ostream &out, const Function &fn) const { @@ -1112,6 +1130,9 @@ namespace ir { for (uint32_t i = 0; i < valueNum; ++i) out << "%" << this->getSrc(fn, i+1) << (i != (valueNum-1u) ? " " : ""); out << "}"; + out << " bti"; + for (uint32_t i = 0; i < bti.count; ++i) + out << ": " << (int)bti.bti[i]; } INLINE void LabelInstruction::out(std::ostream &out, const Function &fn) const { @@ -1183,7 +1204,7 @@ namespace ir { return HelperIntrospection<CLASS, RefClass>::value == 1; #define START_INTROSPECTION(CLASS) \ - static_assert(sizeof(internal::CLASS) == sizeof(uint64_t), \ + static_assert(sizeof(internal::CLASS) == (sizeof(uint64_t)*2), \ "Bad instruction size"); \ static_assert(offsetof(internal::CLASS, opcode) == 0, \ "Bad opcode offset"); \ @@ -1427,14 +1448,17 @@ DECL_MEM_FN(BitCastInstruction, Type, getDstType(void), getDstType()) DECL_MEM_FN(ConvertInstruction, Type, getSrcType(void), getSrcType()) DECL_MEM_FN(ConvertInstruction, Type, getDstType(void), getDstType()) DECL_MEM_FN(AtomicInstruction, AddressSpace, getAddressSpace(void), getAddressSpace()) +DECL_MEM_FN(AtomicInstruction, BTI, getBTI(void), getBTI()) DECL_MEM_FN(AtomicInstruction, AtomicOps, getAtomicOpcode(void), getAtomicOpcode()) DECL_MEM_FN(StoreInstruction, Type, getValueType(void), getValueType()) DECL_MEM_FN(StoreInstruction, uint32_t, getValueNum(void), getValueNum()) DECL_MEM_FN(StoreInstruction, AddressSpace, getAddressSpace(void), getAddressSpace()) +DECL_MEM_FN(StoreInstruction, BTI, getBTI(void), getBTI()) DECL_MEM_FN(StoreInstruction, bool, isAligned(void), isAligned()) DECL_MEM_FN(LoadInstruction, Type, getValueType(void), getValueType()) DECL_MEM_FN(LoadInstruction, uint32_t, getValueNum(void), getValueNum()) DECL_MEM_FN(LoadInstruction, AddressSpace, getAddressSpace(void), getAddressSpace()) +DECL_MEM_FN(LoadInstruction, BTI, getBTI(void), getBTI()) DECL_MEM_FN(LoadInstruction, bool, isAligned(void), isAligned()) DECL_MEM_FN(LoadImmInstruction, Type, getType(void), getType()) DECL_MEM_FN(LabelInstruction, LabelIndex, getLabelIndex(void), getLabelIndex()) @@ -1578,8 +1602,8 @@ DECL_MEM_FN(GetImageInfoInstruction, const uint8_t, getImageIndex(void), getImag } // For all unary functions with given opcode - Instruction ATOMIC(AtomicOps atomicOp, Register dst, AddressSpace space, Tuple src) { - return internal::AtomicInstruction(atomicOp, dst, space, src).convert(); + Instruction ATOMIC(AtomicOps atomicOp, Register dst, AddressSpace space, BTI bti, Tuple src) { + return internal::AtomicInstruction(atomicOp, dst, space, bti, src).convert(); } // BRA @@ -1621,9 +1645,10 @@ DECL_MEM_FN(GetImageInfoInstruction, const uint8_t, getImageIndex(void), getImag Register offset, \ AddressSpace space, \ uint32_t valueNum, \ - bool dwAligned) \ + bool dwAligned, \ + BTI bti) \ { \ - return internal::CLASS(type,tuple,offset,space,valueNum,dwAligned).convert(); \ + return internal::CLASS(type,tuple,offset,space,valueNum,dwAligned,bti).convert(); \ } DECL_EMIT_FUNCTION(LOAD, LoadInstruction) diff --git a/backend/src/ir/instruction.hpp b/backend/src/ir/instruction.hpp index ada780f5..e4c415ef 100644 --- a/backend/src/ir/instruction.hpp +++ b/backend/src/ir/instruction.hpp @@ -31,9 +31,14 @@ #include "sys/intrusive_list.hpp" #include <ostream> +#define MAX_MIXED_POINTER 4 namespace gbe { namespace ir { + struct BTI { + uint8_t bti[MAX_MIXED_POINTER]; + uint8_t count; + }; /*! All opcodes */ enum Opcode : uint8_t { @@ -95,7 +100,7 @@ namespace ir { /////////////////////////////////////////////////////////////////////////// /*! Stores instruction internal data and opcode */ - class ALIGNED(sizeof(uint64_t)) InstructionBase + class ALIGNED(sizeof(uint64_t)*2) InstructionBase { public: /*! Initialize the instruction from a 8 bytes stream */ @@ -109,7 +114,7 @@ namespace ir { /*! Get the instruction opcode */ INLINE Opcode getOpcode(void) const { return opcode; } protected: - enum { opaqueSize = sizeof(uint64_t)-sizeof(uint8_t) }; + enum { opaqueSize = sizeof(uint64_t)*2-sizeof(uint8_t) }; Opcode opcode; //!< Idendifies the instruction char opaque[opaqueSize]; //!< Remainder of it GBE_CLASS(InstructionBase); //!< Use internal allocators @@ -273,6 +278,7 @@ namespace ir { static const uint32_t addressIndex = 0; /*! Address space that is manipulated here */ AddressSpace getAddressSpace(void) const; + BTI getBTI(void) const; /*! Return the atomic function code */ AtomicOps getAtomicOpcode(void) const; /*! Return the register that contains the addresses */ @@ -292,6 +298,7 @@ namespace ir { Type getValueType(void) const; /*! Give the number of values the instruction is storing (srcNum-1) */ uint32_t getValueNum(void) const; + BTI getBTI(void) const; /*! Address space that is manipulated here */ AddressSpace getAddressSpace(void) const; /*! DWORD aligned means untyped read for Gen. That is what matters */ @@ -323,6 +330,7 @@ namespace ir { bool isAligned(void) const; /*! Return the register that contains the addresses */ INLINE Register getAddress(void) const { return this->getSrc(0u); } + BTI getBTI(void) const; /*! Return the register that contain value valueID */ INLINE Register getValue(uint32_t valueID) const { return this->getDst(valueID); @@ -644,7 +652,7 @@ namespace ir { /*! F32TO16.{dstType <- srcType} dst src */ Instruction F32TO16(Type dstType, Type srcType, Register dst, Register src); /*! atomic dst addr.space {src1 {src2}} */ - Instruction ATOMIC(AtomicOps opcode, Register dst, AddressSpace space, Tuple src); + Instruction ATOMIC(AtomicOps opcode, Register dst, AddressSpace space, BTI bti, Tuple src); /*! bra labelIndex */ Instruction BRA(LabelIndex labelIndex); /*! (pred) bra labelIndex */ @@ -658,9 +666,9 @@ namespace ir { /*! ret */ Instruction RET(void); /*! load.type.space {dst1,...,dst_valueNum} offset value */ - Instruction LOAD(Type type, Tuple dst, Register offset, AddressSpace space, uint32_t valueNum, bool dwAligned); + Instruction LOAD(Type type, Tuple dst, Register offset, AddressSpace space, uint32_t valueNum, bool dwAligned, BTI bti); /*! store.type.space offset {src1,...,src_valueNum} value */ - Instruction STORE(Type type, Tuple src, Register offset, AddressSpace space, uint32_t valueNum, bool dwAligned); + Instruction STORE(Type type, Tuple src, Register offset, AddressSpace space, uint32_t valueNum, bool dwAligned, BTI bti); /*! loadi.type dst value */ Instruction LOADI(Type type, Register dst, ImmediateIndex value); /*! sync.params... (see Sync instruction) */ |