Commit e2e6fa67 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-aug-2018' into staging



MIPS queue August 2018 v6

# gpg: Signature made Fri 24 Aug 2018 16:52:27 BST
# gpg:                using RSA key D4972A8967F75A65
# gpg: Good signature from "Aleksandar Markovic <amarkovic@wavecomp.com>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 8526 FBF1 5DA3 811F 4A01  DD75 D497 2A89 67F7 5A65

* remotes/amarkovic/tags/mips-queue-aug-2018: (45 commits)
  target/mips: Add definition of nanoMIPS I7200 CPU
  mips_malta: Fix semihosting argument passing for nanoMIPS bare metal
  mips_malta: Add setting up GT64120 BARs to the nanoMIPS bootloader
  mips_malta: Add basic nanoMIPS boot code for Malta board
  elf: Don't check FCR31_NAN2008 bit for nanoMIPS
  elf: On elf loading, treat both EM_MIPS and EM_NANOMIPS as legal for MIPS
  elf: Relax MIPS' elf_check_arch() to accept EM_NANOMIPS too
  elf: Add EM_NANOMIPS value as a valid one for e_machine field
  target/mips: Fix ERET/ERETNC behavior related to ADEL exception
  target/mips: Add updating BadInstr and BadInstrX for nanoMIPS
  target/mips: Add availability control via bit NMS
  target/mips: Add emulation of DSP ASE for nanoMIPS - part 6
  target/mips: Add emulation of DSP ASE for nanoMIPS - part 5
  target/mips: Add emulation of DSP ASE for nanoMIPS - part 4
  target/mips: Add emulation of DSP ASE for nanoMIPS - part 3
  target/mips: Add emulation of DSP ASE for nanoMIPS - part 2
  target/mips: Add emulation of DSP ASE for nanoMIPS - part 1
  target/mips: Implement MT ASE support for nanoMIPS
  target/mips: Fix pre-nanoMIPS MT ASE instructions availability control
  target/mips: Add emulation of nanoMIPS 32-bit branch instructions
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 746b7907 d45942d9
Loading
Loading
Loading
Loading
+209 −3
Original line number Diff line number Diff line
@@ -599,6 +599,208 @@ static void network_init(PCIBus *pci_bus)
    }
}

static void write_bootloader_nanomips(uint8_t *base, int64_t run_addr,
                                      int64_t kernel_entry)
{
    uint16_t *p;

    /* Small bootloader */
    p = (uint16_t *)base;

#define NM_HI1(VAL) (((VAL) >> 16) & 0x1f)
#define NM_HI2(VAL) \
          (((VAL) & 0xf000) | (((VAL) >> 19) & 0xffc) | (((VAL) >> 31) & 0x1))
#define NM_LO(VAL)  ((VAL) & 0xfff)

    stw_p(p++, 0x2800); stw_p(p++, 0x001c);
                                /* bc to_here */
    stw_p(p++, 0x8000); stw_p(p++, 0xc000);
                                /* nop */
    stw_p(p++, 0x8000); stw_p(p++, 0xc000);
                                /* nop */
    stw_p(p++, 0x8000); stw_p(p++, 0xc000);
                                /* nop */
    stw_p(p++, 0x8000); stw_p(p++, 0xc000);
                                /* nop */
    stw_p(p++, 0x8000); stw_p(p++, 0xc000);
                                /* nop */
    stw_p(p++, 0x8000); stw_p(p++, 0xc000);
                                /* nop */
    stw_p(p++, 0x8000); stw_p(p++, 0xc000);
                                /* nop */

    /* to_here: */
    if (semihosting_get_argc()) {
        /* Preserve a0 content as arguments have been passed    */
        stw_p(p++, 0x8000); stw_p(p++, 0xc000);
                                /* nop                          */
    } else {
        stw_p(p++, 0x0080); stw_p(p++, 0x0002);
                                /* li a0,2                      */
    }

    stw_p(p++, 0xe3a0 | NM_HI1(ENVP_ADDR - 64));

    stw_p(p++, NM_HI2(ENVP_ADDR - 64));
                                /* lui sp,%hi(ENVP_ADDR - 64)   */

    stw_p(p++, 0x83bd); stw_p(p++, NM_LO(ENVP_ADDR - 64));
                                /* ori sp,sp,%lo(ENVP_ADDR - 64) */

    stw_p(p++, 0xe0a0 | NM_HI1(ENVP_ADDR));

    stw_p(p++, NM_HI2(ENVP_ADDR));
                                /* lui a1,%hi(ENVP_ADDR)        */

    stw_p(p++, 0x80a5); stw_p(p++, NM_LO(ENVP_ADDR));
                                /* ori a1,a1,%lo(ENVP_ADDR)     */

    stw_p(p++, 0xe0c0 | NM_HI1(ENVP_ADDR + 8));

    stw_p(p++, NM_HI2(ENVP_ADDR + 8));
                                /* lui a2,%hi(ENVP_ADDR + 8)    */

    stw_p(p++, 0x80c6); stw_p(p++, NM_LO(ENVP_ADDR + 8));
                                /* ori a2,a2,%lo(ENVP_ADDR + 8) */

    stw_p(p++, 0xe0e0 | NM_HI1(loaderparams.ram_low_size));

    stw_p(p++, NM_HI2(loaderparams.ram_low_size));
                                /* lui a3,%hi(loaderparams.ram_low_size) */

    stw_p(p++, 0x80e7); stw_p(p++, NM_LO(loaderparams.ram_low_size));
                                /* ori a3,a3,%lo(loaderparams.ram_low_size) */

    /*
     * Load BAR registers as done by YAMON:
     *
     *  - set up PCI0 I/O BARs from 0x18000000 to 0x181fffff
     *  - set up PCI0 MEM0 at 0x10000000, size 0x8000000
     *  - set up PCI0 MEM1 at 0x18200000, size 0xbe00000
     *
     */
    stw_p(p++, 0xe040); stw_p(p++, 0x0681);
                                /* lui t1, %hi(0xb4000000)      */

#ifdef TARGET_WORDS_BIGENDIAN

    stw_p(p++, 0xe020); stw_p(p++, 0x0be1);
                                /* lui t0, %hi(0xdf000000)      */

    /* 0x68 corresponds to GT_ISD (from hw/mips/gt64xxx_pci.c)  */
    stw_p(p++, 0x8422); stw_p(p++, 0x9068);
                                /* sw t0, 0x68(t1)              */

    stw_p(p++, 0xe040); stw_p(p++, 0x077d);
                                /* lui t1, %hi(0xbbe00000)      */

    stw_p(p++, 0xe020); stw_p(p++, 0x0801);
                                /* lui t0, %hi(0xc0000000)      */

    /* 0x48 corresponds to GT_PCI0IOLD                          */
    stw_p(p++, 0x8422); stw_p(p++, 0x9048);
                                /* sw t0, 0x48(t1)              */

    stw_p(p++, 0xe020); stw_p(p++, 0x0800);
                                /* lui t0, %hi(0x40000000)      */

    /* 0x50 corresponds to GT_PCI0IOHD                          */
    stw_p(p++, 0x8422); stw_p(p++, 0x9050);
                                /* sw t0, 0x50(t1)              */

    stw_p(p++, 0xe020); stw_p(p++, 0x0001);
                                /* lui t0, %hi(0x80000000)      */

    /* 0x58 corresponds to GT_PCI0M0LD                          */
    stw_p(p++, 0x8422); stw_p(p++, 0x9058);
                                /* sw t0, 0x58(t1)              */

    stw_p(p++, 0xe020); stw_p(p++, 0x07e0);
                                /* lui t0, %hi(0x3f000000)      */

    /* 0x60 corresponds to GT_PCI0M0HD                          */
    stw_p(p++, 0x8422); stw_p(p++, 0x9060);
                                /* sw t0, 0x60(t1)              */

    stw_p(p++, 0xe020); stw_p(p++, 0x0821);
                                /* lui t0, %hi(0xc1000000)      */

    /* 0x80 corresponds to GT_PCI0M1LD                          */
    stw_p(p++, 0x8422); stw_p(p++, 0x9080);
                                /* sw t0, 0x80(t1)              */

    stw_p(p++, 0xe020); stw_p(p++, 0x0bc0);
                                /* lui t0, %hi(0x5e000000)      */

#else

    stw_p(p++, 0x0020); stw_p(p++, 0x00df);
                                /* addiu[32] t0, $0, 0xdf       */

    /* 0x68 corresponds to GT_ISD                               */
    stw_p(p++, 0x8422); stw_p(p++, 0x9068);
                                /* sw t0, 0x68(t1)              */

    /* Use kseg2 remapped address 0x1be00000                    */
    stw_p(p++, 0xe040); stw_p(p++, 0x077d);
                                /* lui t1, %hi(0xbbe00000)      */

    stw_p(p++, 0x0020); stw_p(p++, 0x00c0);
                                /* addiu[32] t0, $0, 0xc0       */

    /* 0x48 corresponds to GT_PCI0IOLD                          */
    stw_p(p++, 0x8422); stw_p(p++, 0x9048);
                                /* sw t0, 0x48(t1)              */

    stw_p(p++, 0x0020); stw_p(p++, 0x0040);
                                /* addiu[32] t0, $0, 0x40       */

    /* 0x50 corresponds to GT_PCI0IOHD                          */
    stw_p(p++, 0x8422); stw_p(p++, 0x9050);
                                /* sw t0, 0x50(t1)              */

    stw_p(p++, 0x0020); stw_p(p++, 0x0080);
                                /* addiu[32] t0, $0, 0x80       */

    /* 0x58 corresponds to GT_PCI0M0LD                          */
    stw_p(p++, 0x8422); stw_p(p++, 0x9058);
                                /* sw t0, 0x58(t1)              */

    stw_p(p++, 0x0020); stw_p(p++, 0x003f);
                                /* addiu[32] t0, $0, 0x3f       */

    /* 0x60 corresponds to GT_PCI0M0HD                          */
    stw_p(p++, 0x8422); stw_p(p++, 0x9060);
                                /* sw t0, 0x60(t1)              */

    stw_p(p++, 0x0020); stw_p(p++, 0x00c1);
                                /* addiu[32] t0, $0, 0xc1       */

    /* 0x80 corresponds to GT_PCI0M1LD                          */
    stw_p(p++, 0x8422); stw_p(p++, 0x9080);
                                /* sw t0, 0x80(t1)              */

    stw_p(p++, 0x0020); stw_p(p++, 0x005e);
                                /* addiu[32] t0, $0, 0x5e       */

#endif

    /* 0x88 corresponds to GT_PCI0M1HD                          */
    stw_p(p++, 0x8422); stw_p(p++, 0x9088);
                                /* sw t0, 0x88(t1)              */

    stw_p(p++, 0xe320 | NM_HI1(kernel_entry));

    stw_p(p++, NM_HI2(kernel_entry));
                                /* lui t9,%hi(kernel_entry)     */

    stw_p(p++, 0x8339); stw_p(p++, NM_LO(kernel_entry));
                                /* ori t9,t9,%lo(kernel_entry)  */

    stw_p(p++, 0x4bf9); stw_p(p++, 0x0000);
                                /* jalrc   t8                   */
}

/* ROM and pseudo bootloader

   The following code implements a very very simple bootloader. It first
@@ -620,7 +822,6 @@ static void network_init(PCIBus *pci_bus)
     a2 - 32-bit address of the environment variables table
     a3 - RAM size in bytes
*/

static void write_bootloader(uint8_t *base, int64_t run_addr,
                             int64_t kernel_entry)
{
@@ -1096,8 +1297,13 @@ void mips_malta_init(MachineState *machine)
        loaderparams.initrd_filename = initrd_filename;
        kernel_entry = load_kernel();

        if (!cpu_supports_isa(machine->cpu_type, ISA_NANOMIPS32)) {
            write_bootloader(memory_region_get_ram_ptr(bios),
                             bootloader_run_addr, kernel_entry);
        } else {
            write_bootloader_nanomips(memory_region_get_ram_ptr(bios),
                                      bootloader_run_addr, kernel_entry);
        }
        if (kvm_enabled()) {
            /* Write the bootloader code @ the end of RAM, 1MB reserved */
            write_bootloader(memory_region_get_ram_ptr(ram_low_preio) +
+2 −0
Original line number Diff line number Diff line
@@ -143,6 +143,8 @@ typedef int64_t Elf64_Sxword;

#define EM_RISCV        243     /* RISC-V */

#define EM_NANOMIPS     249     /* Wave Computing nanoMIPS */

/*
 * This is an interim value that we will use until the committee comes
 * up with a final number.
+8 −0
Original line number Diff line number Diff line
@@ -327,6 +327,14 @@ static int glue(load_elf, SZ)(const char *name, int fd,
                }
            }
            break;
        case EM_MIPS:
        case EM_NANOMIPS:
            if ((ehdr.e_machine != EM_MIPS) &&
                (ehdr.e_machine != EM_NANOMIPS)) {
                ret = ELF_LOAD_WRONG_ARCH;
                goto fail;
            }
            break;
        default:
            if (elf_machine != ehdr.e_machine) {
                ret = ELF_LOAD_WRONG_ARCH;
+2 −0
Original line number Diff line number Diff line
@@ -853,6 +853,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *en
#endif
#define ELF_ARCH    EM_MIPS

#define elf_check_arch(x) ((x) == EM_MIPS || (x) == EM_NANOMIPS)

static inline void init_thread(struct target_pt_regs *regs,
                               struct image_info *infop)
{
+23 −5
Original line number Diff line number Diff line
@@ -397,10 +397,13 @@ static int do_store_exclusive(CPUMIPSState *env)
    target_ulong addr;
    target_ulong page_addr;
    target_ulong val;
    uint32_t val_wp = 0;
    uint32_t llnewval_wp = 0;
    int flags;
    int segv = 0;
    int reg;
    int d;
    int wp;

    addr = env->lladdr;
    page_addr = addr & TARGET_PAGE_MASK;
@@ -412,20 +415,32 @@ static int do_store_exclusive(CPUMIPSState *env)
    } else {
        reg = env->llreg & 0x1f;
        d = (env->llreg & 0x20) != 0;
        wp = (env->llreg & 0x40) != 0;
        if (!wp) {
            if (d) {
                segv = get_user_s64(val, addr);
            } else {
                segv = get_user_s32(val, addr);
            }
        } else {
            segv = get_user_s32(val, addr);
            segv |= get_user_s32(val_wp, addr);
            llnewval_wp = env->llnewval_wp;
        }
        if (!segv) {
            if (val != env->llval) {
            if (val != env->llval && val_wp == llnewval_wp) {
                env->active_tc.gpr[reg] = 0;
            } else {
                if (!wp) {
                    if (d) {
                        segv = put_user_u64(env->llnewval, addr);
                    } else {
                        segv = put_user_u32(env->llnewval, addr);
                    }
                } else {
                    segv = put_user_u32(env->llnewval, addr);
                    segv |= put_user_u32(env->llnewval_wp, addr + 4);
                }
                if (!segv) {
                    env->active_tc.gpr[reg] = 1;
                }
@@ -732,6 +747,9 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
    if (regs->cp0_epc & 1) {
        env->hflags |= MIPS_HFLAG_M16;
    }
    if (env->insn_flags & ISA_NANOMIPS32) {
        return;
    }
    if (((info->elf_flags & EF_MIPS_NAN2008) != 0) !=
        ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) {
        if ((env->active_fpu.fcr31_rw_bitmask &
Loading