diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
commit | 2c3c1048746a4622d8c89a29670120dc8fab93c4 (patch) | |
tree | 848558de17fb3008cdf4d861b01ac7781903ce39 /arch/microblaze/include/asm/flat.h | |
parent | Initial commit. (diff) | |
download | linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.tar.xz linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.zip |
Adding upstream version 6.1.76.upstream/6.1.76
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'arch/microblaze/include/asm/flat.h')
-rw-r--r-- | arch/microblaze/include/asm/flat.h | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/arch/microblaze/include/asm/flat.h b/arch/microblaze/include/asm/flat.h new file mode 100644 index 000000000..79a749f4a --- /dev/null +++ b/arch/microblaze/include/asm/flat.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * uClinux flat-format executables + * + * Copyright (C) 2005 John Williams <jwilliams@itee.uq.edu.au> + */ + +#ifndef _ASM_MICROBLAZE_FLAT_H +#define _ASM_MICROBLAZE_FLAT_H + +#include <asm/unaligned.h> + +/* + * Microblaze works a little differently from other arches, because + * of the MICROBLAZE_64 reloc type. Here, a 32 bit address is split + * over two instructions, an 'imm' instruction which provides the top + * 16 bits, then the instruction "proper" which provides the low 16 + * bits. + */ + +/* + * Crack open a symbol reference and extract the address to be + * relocated. rp is a potentially unaligned pointer to the + * reference + */ + +static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags, + u32 *addr) +{ + u32 *p = (__force u32 *)rp; + + /* Is it a split 64/32 reference? */ + if (relval & 0x80000000) { + /* Grab the two halves of the reference */ + u32 val_hi, val_lo; + + val_hi = get_unaligned(p); + val_lo = get_unaligned(p+1); + + /* Crack the address out */ + *addr = ((val_hi & 0xffff) << 16) + (val_lo & 0xffff); + } else { + /* Get the address straight out */ + *addr = get_unaligned(p); + } + + return 0; +} + +/* + * Insert an address into the symbol reference at rp. rp is potentially + * unaligned. + */ + +static inline int +flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 relval) +{ + u32 *p = (__force u32 *)rp; + /* Is this a split 64/32 reloc? */ + if (relval & 0x80000000) { + /* Get the two "halves" */ + unsigned long val_hi = get_unaligned(p); + unsigned long val_lo = get_unaligned(p + 1); + + /* insert the address */ + val_hi = (val_hi & 0xffff0000) | addr >> 16; + val_lo = (val_lo & 0xffff0000) | (addr & 0xffff); + + /* store the two halves back into memory */ + put_unaligned(val_hi, p); + put_unaligned(val_lo, p+1); + } else { + /* Put it straight in, no messing around */ + put_unaligned(addr, p); + } + return 0; +} + +#define flat_get_relocate_addr(rel) (rel & 0x7fffffff) + +#endif /* _ASM_MICROBLAZE_FLAT_H */ |