mirror of
https://github.com/torvalds/linux.git
synced 2025-12-01 07:26:02 +07:00
Merge tag 'loongarch-fixes-6.17-2' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
Pull LoongArch fixes from Huacai Chen: "Fix some build warnings for RUST-enabled objtool check, align ACPI structures for ARCH_STRICT_ALIGN, fix an unreliable stack for live patching, add some NULL pointer checkings, and fix some bugs around KVM" * tag 'loongarch-fixes-6.17-2' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson: LoongArch: KVM: Avoid copy_*_user() with lock hold in kvm_pch_pic_regs_access() LoongArch: KVM: Avoid copy_*_user() with lock hold in kvm_eiointc_sw_status_access() LoongArch: KVM: Avoid copy_*_user() with lock hold in kvm_eiointc_regs_access() LoongArch: KVM: Avoid copy_*_user() with lock hold in kvm_eiointc_ctrl_access() LoongArch: KVM: Fix VM migration failure with PTW enabled LoongArch: KVM: Remove unused returns and semicolons LoongArch: vDSO: Check kcalloc() result in init_vdso() LoongArch: Fix unreliable stack for live patching LoongArch: Replace sprintf() with sysfs_emit() LoongArch: Check the return value when creating kobj LoongArch: Align ACPI structures if ARCH_STRICT_ALIGN enabled LoongArch: Update help info of ARCH_STRICT_ALIGN LoongArch: Handle jump tables options for RUST LoongArch: Make LTO case independent in Makefile objtool/LoongArch: Mark special atomic instruction as INSN_BUG type objtool/LoongArch: Mark types based on break immediate code
This commit is contained in:
@@ -298,6 +298,10 @@ config AS_HAS_LVZ_EXTENSION
|
||||
config CC_HAS_ANNOTATE_TABLEJUMP
|
||||
def_bool $(cc-option,-mannotate-tablejump)
|
||||
|
||||
config RUSTC_HAS_ANNOTATE_TABLEJUMP
|
||||
depends on RUST
|
||||
def_bool $(rustc-option,-Cllvm-args=--loongarch-annotate-tablejump)
|
||||
|
||||
menu "Kernel type and options"
|
||||
|
||||
source "kernel/Kconfig.hz"
|
||||
@@ -563,10 +567,14 @@ config ARCH_STRICT_ALIGN
|
||||
-mstrict-align build parameter to prevent unaligned accesses.
|
||||
|
||||
CPUs with h/w unaligned access support:
|
||||
Loongson-2K2000/2K3000/3A5000/3C5000/3D5000.
|
||||
Loongson-2K2000/2K3000 and all of Loongson-3 series processors
|
||||
based on LoongArch.
|
||||
|
||||
CPUs without h/w unaligned access support:
|
||||
Loongson-2K500/2K1000.
|
||||
Loongson-2K0300/2K0500/2K1000.
|
||||
|
||||
If you want to make sure whether to support unaligned memory access
|
||||
on your hardware, please read the bit 20 (UAL) of CPUCFG1 register.
|
||||
|
||||
This option is enabled by default to make the kernel be able to run
|
||||
on all LoongArch systems. But you can disable it manually if you want
|
||||
|
||||
@@ -102,16 +102,21 @@ KBUILD_CFLAGS += $(call cc-option,-mthin-add-sub) $(call cc-option,-Wa$(comma)
|
||||
|
||||
ifdef CONFIG_OBJTOOL
|
||||
ifdef CONFIG_CC_HAS_ANNOTATE_TABLEJUMP
|
||||
KBUILD_CFLAGS += -mannotate-tablejump
|
||||
else
|
||||
KBUILD_CFLAGS += -fno-jump-tables # keep compatibility with older compilers
|
||||
endif
|
||||
ifdef CONFIG_RUSTC_HAS_ANNOTATE_TABLEJUMP
|
||||
KBUILD_RUSTFLAGS += -Cllvm-args=--loongarch-annotate-tablejump
|
||||
else
|
||||
KBUILD_RUSTFLAGS += -Zno-jump-tables # keep compatibility with older compilers
|
||||
endif
|
||||
ifdef CONFIG_LTO_CLANG
|
||||
# The annotate-tablejump option can not be passed to LLVM backend when LTO is enabled.
|
||||
# Ensure it is aware of linker with LTO, '--loongarch-annotate-tablejump' also needs to
|
||||
# be passed via '-mllvm' to ld.lld.
|
||||
KBUILD_CFLAGS += -mannotate-tablejump
|
||||
ifdef CONFIG_LTO_CLANG
|
||||
KBUILD_LDFLAGS += -mllvm --loongarch-annotate-tablejump
|
||||
endif
|
||||
else
|
||||
KBUILD_CFLAGS += -fno-jump-tables # keep compatibility with older compilers
|
||||
endif
|
||||
endif
|
||||
|
||||
KBUILD_RUSTFLAGS += --target=loongarch64-unknown-none-softfloat -Ccode-model=small
|
||||
|
||||
@@ -10,9 +10,8 @@
|
||||
#ifndef _ASM_LOONGARCH_ACENV_H
|
||||
#define _ASM_LOONGARCH_ACENV_H
|
||||
|
||||
/*
|
||||
* This header is required by ACPI core, but we have nothing to fill in
|
||||
* right now. Will be updated later when needed.
|
||||
*/
|
||||
#ifdef CONFIG_ARCH_STRICT_ALIGN
|
||||
#define ACPI_MISALIGNMENT_NOT_SUPPORTED
|
||||
#endif /* CONFIG_ARCH_STRICT_ALIGN */
|
||||
|
||||
#endif /* _ASM_LOONGARCH_ACENV_H */
|
||||
|
||||
@@ -16,6 +16,13 @@
|
||||
*/
|
||||
#define KVM_MMU_CACHE_MIN_PAGES (CONFIG_PGTABLE_LEVELS - 1)
|
||||
|
||||
/*
|
||||
* _PAGE_MODIFIED is a SW pte bit, it records page ever written on host
|
||||
* kernel, on secondary MMU it records the page writeable attribute, in
|
||||
* order for fast path handling.
|
||||
*/
|
||||
#define KVM_PAGE_WRITEABLE _PAGE_MODIFIED
|
||||
|
||||
#define _KVM_FLUSH_PGTABLE 0x1
|
||||
#define _KVM_HAS_PGMASK 0x2
|
||||
#define kvm_pfn_pte(pfn, prot) (((pfn) << PFN_PTE_SHIFT) | pgprot_val(prot))
|
||||
@@ -52,10 +59,10 @@ static inline void kvm_set_pte(kvm_pte_t *ptep, kvm_pte_t val)
|
||||
WRITE_ONCE(*ptep, val);
|
||||
}
|
||||
|
||||
static inline int kvm_pte_write(kvm_pte_t pte) { return pte & _PAGE_WRITE; }
|
||||
static inline int kvm_pte_dirty(kvm_pte_t pte) { return pte & _PAGE_DIRTY; }
|
||||
static inline int kvm_pte_young(kvm_pte_t pte) { return pte & _PAGE_ACCESSED; }
|
||||
static inline int kvm_pte_huge(kvm_pte_t pte) { return pte & _PAGE_HUGE; }
|
||||
static inline int kvm_pte_dirty(kvm_pte_t pte) { return pte & __WRITEABLE; }
|
||||
static inline int kvm_pte_writeable(kvm_pte_t pte) { return pte & KVM_PAGE_WRITEABLE; }
|
||||
|
||||
static inline kvm_pte_t kvm_pte_mkyoung(kvm_pte_t pte)
|
||||
{
|
||||
@@ -69,12 +76,12 @@ static inline kvm_pte_t kvm_pte_mkold(kvm_pte_t pte)
|
||||
|
||||
static inline kvm_pte_t kvm_pte_mkdirty(kvm_pte_t pte)
|
||||
{
|
||||
return pte | _PAGE_DIRTY;
|
||||
return pte | __WRITEABLE;
|
||||
}
|
||||
|
||||
static inline kvm_pte_t kvm_pte_mkclean(kvm_pte_t pte)
|
||||
{
|
||||
return pte & ~_PAGE_DIRTY;
|
||||
return pte & ~__WRITEABLE;
|
||||
}
|
||||
|
||||
static inline kvm_pte_t kvm_pte_mkhuge(kvm_pte_t pte)
|
||||
@@ -87,6 +94,11 @@ static inline kvm_pte_t kvm_pte_mksmall(kvm_pte_t pte)
|
||||
return pte & ~_PAGE_HUGE;
|
||||
}
|
||||
|
||||
static inline kvm_pte_t kvm_pte_mkwriteable(kvm_pte_t pte)
|
||||
{
|
||||
return pte | KVM_PAGE_WRITEABLE;
|
||||
}
|
||||
|
||||
static inline int kvm_need_flush(kvm_ptw_ctx *ctx)
|
||||
{
|
||||
return ctx->flag & _KVM_FLUSH_PGTABLE;
|
||||
|
||||
@@ -86,7 +86,7 @@ late_initcall(fdt_cpu_clk_init);
|
||||
static ssize_t boardinfo_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf,
|
||||
return sysfs_emit(buf,
|
||||
"BIOS Information\n"
|
||||
"Vendor\t\t\t: %s\n"
|
||||
"Version\t\t\t: %s\n"
|
||||
@@ -109,6 +109,8 @@ static int __init boardinfo_init(void)
|
||||
struct kobject *loongson_kobj;
|
||||
|
||||
loongson_kobj = kobject_create_and_add("loongson", firmware_kobj);
|
||||
if (!loongson_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
return sysfs_create_file(loongson_kobj, &boardinfo_attr.attr);
|
||||
}
|
||||
|
||||
@@ -51,12 +51,13 @@ int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
|
||||
if (task == current) {
|
||||
regs->regs[3] = (unsigned long)__builtin_frame_address(0);
|
||||
regs->csr_era = (unsigned long)__builtin_return_address(0);
|
||||
regs->regs[22] = 0;
|
||||
} else {
|
||||
regs->regs[3] = thread_saved_fp(task);
|
||||
regs->csr_era = thread_saved_ra(task);
|
||||
regs->regs[22] = task->thread.reg22;
|
||||
}
|
||||
regs->regs[1] = 0;
|
||||
regs->regs[22] = 0;
|
||||
|
||||
for (unwind_start(&state, task, regs);
|
||||
!unwind_done(&state) && !unwind_error(&state); unwind_next_frame(&state)) {
|
||||
|
||||
@@ -54,6 +54,9 @@ static int __init init_vdso(void)
|
||||
vdso_info.code_mapping.pages =
|
||||
kcalloc(vdso_info.size / PAGE_SIZE, sizeof(struct page *), GFP_KERNEL);
|
||||
|
||||
if (!vdso_info.code_mapping.pages)
|
||||
return -ENOMEM;
|
||||
|
||||
pfn = __phys_to_pfn(__pa_symbol(vdso_info.vdso));
|
||||
for (i = 0; i < vdso_info.size / PAGE_SIZE; i++)
|
||||
vdso_info.code_mapping.pages[i] = pfn_to_page(pfn + i);
|
||||
|
||||
@@ -778,10 +778,8 @@ static long kvm_save_notify(struct kvm_vcpu *vcpu)
|
||||
return 0;
|
||||
default:
|
||||
return KVM_HCALL_INVALID_CODE;
|
||||
};
|
||||
|
||||
return KVM_HCALL_INVALID_CODE;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* kvm_handle_lsx_disabled() - Guest used LSX while disabled in root.
|
||||
|
||||
@@ -426,21 +426,26 @@ static int kvm_eiointc_ctrl_access(struct kvm_device *dev,
|
||||
struct loongarch_eiointc *s = dev->kvm->arch.eiointc;
|
||||
|
||||
data = (void __user *)attr->addr;
|
||||
switch (type) {
|
||||
case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_NUM_CPU:
|
||||
case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_FEATURE:
|
||||
if (copy_from_user(&val, data, 4))
|
||||
return -EFAULT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&s->lock, flags);
|
||||
switch (type) {
|
||||
case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_NUM_CPU:
|
||||
if (copy_from_user(&val, data, 4))
|
||||
ret = -EFAULT;
|
||||
else {
|
||||
if (val >= EIOINTC_ROUTE_MAX_VCPUS)
|
||||
ret = -EINVAL;
|
||||
else
|
||||
s->num_cpu = val;
|
||||
}
|
||||
if (val >= EIOINTC_ROUTE_MAX_VCPUS)
|
||||
ret = -EINVAL;
|
||||
else
|
||||
s->num_cpu = val;
|
||||
break;
|
||||
case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_FEATURE:
|
||||
if (copy_from_user(&s->features, data, 4))
|
||||
ret = -EFAULT;
|
||||
s->features = val;
|
||||
if (!(s->features & BIT(EIOINTC_HAS_VIRT_EXTENSION)))
|
||||
s->status |= BIT(EIOINTC_ENABLE);
|
||||
break;
|
||||
@@ -462,19 +467,17 @@ static int kvm_eiointc_ctrl_access(struct kvm_device *dev,
|
||||
|
||||
static int kvm_eiointc_regs_access(struct kvm_device *dev,
|
||||
struct kvm_device_attr *attr,
|
||||
bool is_write)
|
||||
bool is_write, int *data)
|
||||
{
|
||||
int addr, cpu, offset, ret = 0;
|
||||
unsigned long flags;
|
||||
void *p = NULL;
|
||||
void __user *data;
|
||||
struct loongarch_eiointc *s;
|
||||
|
||||
s = dev->kvm->arch.eiointc;
|
||||
addr = attr->attr;
|
||||
cpu = addr >> 16;
|
||||
addr &= 0xffff;
|
||||
data = (void __user *)attr->addr;
|
||||
switch (addr) {
|
||||
case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
|
||||
offset = (addr - EIOINTC_NODETYPE_START) / 4;
|
||||
@@ -513,13 +516,10 @@ static int kvm_eiointc_regs_access(struct kvm_device *dev,
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&s->lock, flags);
|
||||
if (is_write) {
|
||||
if (copy_from_user(p, data, 4))
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
if (copy_to_user(data, p, 4))
|
||||
ret = -EFAULT;
|
||||
}
|
||||
if (is_write)
|
||||
memcpy(p, data, 4);
|
||||
else
|
||||
memcpy(data, p, 4);
|
||||
spin_unlock_irqrestore(&s->lock, flags);
|
||||
|
||||
return ret;
|
||||
@@ -527,19 +527,17 @@ static int kvm_eiointc_regs_access(struct kvm_device *dev,
|
||||
|
||||
static int kvm_eiointc_sw_status_access(struct kvm_device *dev,
|
||||
struct kvm_device_attr *attr,
|
||||
bool is_write)
|
||||
bool is_write, int *data)
|
||||
{
|
||||
int addr, ret = 0;
|
||||
unsigned long flags;
|
||||
void *p = NULL;
|
||||
void __user *data;
|
||||
struct loongarch_eiointc *s;
|
||||
|
||||
s = dev->kvm->arch.eiointc;
|
||||
addr = attr->attr;
|
||||
addr &= 0xffff;
|
||||
|
||||
data = (void __user *)attr->addr;
|
||||
switch (addr) {
|
||||
case KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_NUM_CPU:
|
||||
if (is_write)
|
||||
@@ -561,13 +559,10 @@ static int kvm_eiointc_sw_status_access(struct kvm_device *dev,
|
||||
return -EINVAL;
|
||||
}
|
||||
spin_lock_irqsave(&s->lock, flags);
|
||||
if (is_write) {
|
||||
if (copy_from_user(p, data, 4))
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
if (copy_to_user(data, p, 4))
|
||||
ret = -EFAULT;
|
||||
}
|
||||
if (is_write)
|
||||
memcpy(p, data, 4);
|
||||
else
|
||||
memcpy(data, p, 4);
|
||||
spin_unlock_irqrestore(&s->lock, flags);
|
||||
|
||||
return ret;
|
||||
@@ -576,11 +571,27 @@ static int kvm_eiointc_sw_status_access(struct kvm_device *dev,
|
||||
static int kvm_eiointc_get_attr(struct kvm_device *dev,
|
||||
struct kvm_device_attr *attr)
|
||||
{
|
||||
int ret, data;
|
||||
|
||||
switch (attr->group) {
|
||||
case KVM_DEV_LOONGARCH_EXTIOI_GRP_REGS:
|
||||
return kvm_eiointc_regs_access(dev, attr, false);
|
||||
ret = kvm_eiointc_regs_access(dev, attr, false, &data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (copy_to_user((void __user *)attr->addr, &data, 4))
|
||||
ret = -EFAULT;
|
||||
|
||||
return ret;
|
||||
case KVM_DEV_LOONGARCH_EXTIOI_GRP_SW_STATUS:
|
||||
return kvm_eiointc_sw_status_access(dev, attr, false);
|
||||
ret = kvm_eiointc_sw_status_access(dev, attr, false, &data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (copy_to_user((void __user *)attr->addr, &data, 4))
|
||||
ret = -EFAULT;
|
||||
|
||||
return ret;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -589,13 +600,21 @@ static int kvm_eiointc_get_attr(struct kvm_device *dev,
|
||||
static int kvm_eiointc_set_attr(struct kvm_device *dev,
|
||||
struct kvm_device_attr *attr)
|
||||
{
|
||||
int data;
|
||||
|
||||
switch (attr->group) {
|
||||
case KVM_DEV_LOONGARCH_EXTIOI_GRP_CTRL:
|
||||
return kvm_eiointc_ctrl_access(dev, attr);
|
||||
case KVM_DEV_LOONGARCH_EXTIOI_GRP_REGS:
|
||||
return kvm_eiointc_regs_access(dev, attr, true);
|
||||
if (copy_from_user(&data, (void __user *)attr->addr, 4))
|
||||
return -EFAULT;
|
||||
|
||||
return kvm_eiointc_regs_access(dev, attr, true, &data);
|
||||
case KVM_DEV_LOONGARCH_EXTIOI_GRP_SW_STATUS:
|
||||
return kvm_eiointc_sw_status_access(dev, attr, true);
|
||||
if (copy_from_user(&data, (void __user *)attr->addr, 4))
|
||||
return -EFAULT;
|
||||
|
||||
return kvm_eiointc_sw_status_access(dev, attr, true, &data);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -348,6 +348,7 @@ static int kvm_pch_pic_regs_access(struct kvm_device *dev,
|
||||
struct kvm_device_attr *attr,
|
||||
bool is_write)
|
||||
{
|
||||
char buf[8];
|
||||
int addr, offset, len = 8, ret = 0;
|
||||
void __user *data;
|
||||
void *p = NULL;
|
||||
@@ -397,17 +398,23 @@ static int kvm_pch_pic_regs_access(struct kvm_device *dev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock(&s->lock);
|
||||
/* write or read value according to is_write */
|
||||
if (is_write) {
|
||||
if (copy_from_user(p, data, len))
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
if (copy_to_user(data, p, len))
|
||||
ret = -EFAULT;
|
||||
if (copy_from_user(buf, data, len))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
spin_lock(&s->lock);
|
||||
if (is_write)
|
||||
memcpy(p, buf, len);
|
||||
else
|
||||
memcpy(buf, p, len);
|
||||
spin_unlock(&s->lock);
|
||||
|
||||
if (!is_write) {
|
||||
if (copy_to_user(data, buf, len))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -569,7 +569,7 @@ static int kvm_map_page_fast(struct kvm_vcpu *vcpu, unsigned long gpa, bool writ
|
||||
/* Track access to pages marked old */
|
||||
new = kvm_pte_mkyoung(*ptep);
|
||||
if (write && !kvm_pte_dirty(new)) {
|
||||
if (!kvm_pte_write(new)) {
|
||||
if (!kvm_pte_writeable(new)) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
@@ -856,9 +856,9 @@ retry:
|
||||
prot_bits |= _CACHE_SUC;
|
||||
|
||||
if (writeable) {
|
||||
prot_bits |= _PAGE_WRITE;
|
||||
prot_bits = kvm_pte_mkwriteable(prot_bits);
|
||||
if (write)
|
||||
prot_bits |= __WRITEABLE;
|
||||
prot_bits = kvm_pte_mkdirty(prot_bits);
|
||||
}
|
||||
|
||||
/* Disable dirty logging on HugePages */
|
||||
@@ -904,7 +904,7 @@ retry:
|
||||
kvm_release_faultin_page(kvm, page, false, writeable);
|
||||
spin_unlock(&kvm->mmu_lock);
|
||||
|
||||
if (prot_bits & _PAGE_DIRTY)
|
||||
if (kvm_pte_dirty(prot_bits))
|
||||
mark_page_dirty_in_slot(kvm, memslot, gfn);
|
||||
|
||||
out:
|
||||
|
||||
@@ -51,6 +51,10 @@ enum reg2i16_op {
|
||||
bgeu_op = 0x1b,
|
||||
};
|
||||
|
||||
enum reg3_op {
|
||||
amswapw_op = 0x70c0,
|
||||
};
|
||||
|
||||
struct reg0i15_format {
|
||||
unsigned int immediate : 15;
|
||||
unsigned int opcode : 17;
|
||||
@@ -96,6 +100,13 @@ struct reg2i16_format {
|
||||
unsigned int opcode : 6;
|
||||
};
|
||||
|
||||
struct reg3_format {
|
||||
unsigned int rd : 5;
|
||||
unsigned int rj : 5;
|
||||
unsigned int rk : 5;
|
||||
unsigned int opcode : 17;
|
||||
};
|
||||
|
||||
union loongarch_instruction {
|
||||
unsigned int word;
|
||||
struct reg0i15_format reg0i15_format;
|
||||
@@ -105,6 +116,7 @@ union loongarch_instruction {
|
||||
struct reg2i12_format reg2i12_format;
|
||||
struct reg2i14_format reg2i14_format;
|
||||
struct reg2i16_format reg2i16_format;
|
||||
struct reg3_format reg3_format;
|
||||
};
|
||||
|
||||
#define LOONGARCH_INSN_SIZE sizeof(union loongarch_instruction)
|
||||
|
||||
@@ -278,6 +278,25 @@ static bool decode_insn_reg2i16_fomat(union loongarch_instruction inst,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool decode_insn_reg3_fomat(union loongarch_instruction inst,
|
||||
struct instruction *insn)
|
||||
{
|
||||
switch (inst.reg3_format.opcode) {
|
||||
case amswapw_op:
|
||||
if (inst.reg3_format.rd == LOONGARCH_GPR_ZERO &&
|
||||
inst.reg3_format.rk == LOONGARCH_GPR_RA &&
|
||||
inst.reg3_format.rj == LOONGARCH_GPR_ZERO) {
|
||||
/* amswap.w $zero, $ra, $zero */
|
||||
insn->type = INSN_BUG;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int arch_decode_instruction(struct objtool_file *file, const struct section *sec,
|
||||
unsigned long offset, unsigned int maxlen,
|
||||
struct instruction *insn)
|
||||
@@ -309,11 +328,19 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
||||
return 0;
|
||||
if (decode_insn_reg2i16_fomat(inst, insn))
|
||||
return 0;
|
||||
if (decode_insn_reg3_fomat(inst, insn))
|
||||
return 0;
|
||||
|
||||
if (inst.word == 0)
|
||||
if (inst.word == 0) {
|
||||
/* andi $zero, $zero, 0x0 */
|
||||
insn->type = INSN_NOP;
|
||||
else if (inst.reg0i15_format.opcode == break_op) {
|
||||
/* break */
|
||||
} else if (inst.reg0i15_format.opcode == break_op &&
|
||||
inst.reg0i15_format.immediate == 0x0) {
|
||||
/* break 0x0 */
|
||||
insn->type = INSN_TRAP;
|
||||
} else if (inst.reg0i15_format.opcode == break_op &&
|
||||
inst.reg0i15_format.immediate == 0x1) {
|
||||
/* break 0x1 */
|
||||
insn->type = INSN_BUG;
|
||||
} else if (inst.reg2_format.opcode == ertn_op) {
|
||||
/* ertn */
|
||||
|
||||
Reference in New Issue
Block a user