Commit 9ae80563 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/xtensa/tags/20190204-xtensa' into staging



target/xtensa: SMP updates and various fixes

- fix CPU wakeup on runstall changes; expose runstall as an IRQ line;
- place mini-bootloader at the BSP reset vector;
- expose CPU core frequency in XTFPGA board FPGA register;
- rearrange access to external interrupts of xtensa cores;
- add MX interrupt distributor and use it on SMP XTFPGA boards;
- add test_mmuhifi_c3 xtensa core variant;
- raise number of CPUs that can be instantiated on XTFPGA boards.

# gpg: Signature made Mon 04 Feb 2019 18:59:32 GMT
# gpg:                using RSA key 2B67854B98E5327DCDEB17D851F9CC91F83FA044
# gpg:                issuer "jcmvbkbc@gmail.com"
# gpg: Good signature from "Max Filippov <filippov@cadence.com>" [unknown]
# gpg:                 aka "Max Filippov <max.filippov@cogentembedded.com>" [full]
# gpg:                 aka "Max Filippov <jcmvbkbc@gmail.com>" [full]
# Primary key fingerprint: 2B67 854B 98E5 327D CDEB  17D8 51F9 CC91 F83F A044

* remotes/xtensa/tags/20190204-xtensa:
  hw/xtensa: xtfpga: raise CPU number limit
  target/xtensa: add test_mmuhifi_c3 core
  hw/xtensa: xtfpga: use MX PIC for SMP
  target/xtensa: add MX interrupt controller
  target/xtensa: expose core runstall as an IRQ line
  target/xtensa: rearrange access to external interrupts
  target/xtensa: drop function xtensa_timer_irq
  target/xtensa: fix access to the INTERRUPT SR
  hw/xtensa: xtfpga: use core frequency
  hw/xtensa: xtfpga: fix bootloader placement in SMP
  target/xtensa: add qemu_cpu_kick to xtensa_runstall

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 773c4a62 174e09b7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
obj-y += mx_pic.o
obj-y += pic_cpu.o
obj-y += sim.o
obj-y += xtensa_memory.o

hw/xtensa/mx_pic.c

0 → 100644
+354 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013 - 2019, Max Filippov, Open Source and Linux Lab.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Open Source and Linux Lab nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/xtensa/mx_pic.h"
#include "qemu/log.h"

#define MX_MAX_CPU 32
#define MX_MAX_IRQ 32

#define MIROUT 0x0
#define MIPICAUSE 0x100
#define MIPISET 0x140
#define MIENG 0x180
#define MIENGSET 0x184
#define MIASG 0x188
#define MIASGSET 0x18c
#define MIPIPART 0x190
#define SYSCFGID 0x1a0
#define MPSCORE 0x200
#define CCON 0x220

struct XtensaMxPic {
    unsigned n_cpu;
    unsigned n_irq;

    uint32_t ext_irq_state;
    uint32_t mieng;
    uint32_t miasg;
    uint32_t mirout[MX_MAX_IRQ];
    uint32_t mipipart;
    uint32_t runstall;

    qemu_irq *irq_inputs;
    struct XtensaMxPicCpu {
        XtensaMxPic *mx;
        qemu_irq *irq;
        qemu_irq runstall;
        uint32_t mipicause;
        uint32_t mirout_cache;
        uint32_t irq_state_cache;
        uint32_t ccon;
        MemoryRegion reg;
    } cpu[MX_MAX_CPU];
};

static uint64_t xtensa_mx_pic_ext_reg_read(void *opaque, hwaddr offset,
                                           unsigned size)
{
    struct XtensaMxPicCpu *mx_cpu = opaque;
    struct XtensaMxPic *mx = mx_cpu->mx;

    if (offset < MIROUT + MX_MAX_IRQ) {
        return mx->mirout[offset - MIROUT];
    } else if (offset >= MIPICAUSE && offset < MIPICAUSE + MX_MAX_CPU) {
        return mx->cpu[offset - MIPICAUSE].mipicause;
    } else {
        switch (offset) {
        case MIENG:
            return mx->mieng;

        case MIASG:
            return mx->miasg;

        case MIPIPART:
            return mx->mipipart;

        case SYSCFGID:
            return ((mx->n_cpu - 1) << 18) | (mx_cpu - mx->cpu);

        case MPSCORE:
            return mx->runstall;

        case CCON:
            return mx_cpu->ccon;

        default:
            qemu_log_mask(LOG_GUEST_ERROR,
                          "unknown RER in MX PIC range: 0x%08x\n",
                          (uint32_t)offset);
            return 0;
        }
    }
}

static uint32_t xtensa_mx_pic_get_ipi_for_cpu(const XtensaMxPic *mx,
                                              unsigned cpu)
{
    uint32_t mipicause = mx->cpu[cpu].mipicause;
    uint32_t mipipart = mx->mipipart;

    return (((mipicause & 1) << (mipipart & 3)) |
            ((mipicause & 0x000e) != 0) << ((mipipart >> 2) & 3) |
            ((mipicause & 0x00f0) != 0) << ((mipipart >> 4) & 3) |
            ((mipicause & 0xff00) != 0) << ((mipipart >> 6) & 3)) & 0x7;
}

static uint32_t xtensa_mx_pic_get_ext_irq_for_cpu(const XtensaMxPic *mx,
                                                  unsigned cpu)
{
    return ((((mx->ext_irq_state & mx->mieng) | mx->miasg) &
             mx->cpu[cpu].mirout_cache) << 2) |
        xtensa_mx_pic_get_ipi_for_cpu(mx, cpu);
}

static void xtensa_mx_pic_update_cpu(XtensaMxPic *mx, unsigned cpu)
{
    uint32_t irq = xtensa_mx_pic_get_ext_irq_for_cpu(mx, cpu);
    uint32_t changed_irq = mx->cpu[cpu].irq_state_cache ^ irq;
    unsigned i;

    qemu_log_mask(CPU_LOG_INT, "%s: CPU %d, irq: %08x, changed_irq: %08x\n",
                  __func__, cpu, irq, changed_irq);
    mx->cpu[cpu].irq_state_cache = irq;
    for (i = 0; changed_irq; ++i) {
        uint32_t mask = 1u << i;

        if (changed_irq & mask) {
            changed_irq ^= mask;
            qemu_set_irq(mx->cpu[cpu].irq[i], irq & mask);
        }
    }
}

static void xtensa_mx_pic_update_all(XtensaMxPic *mx)
{
    unsigned cpu;

    for (cpu = 0; cpu < mx->n_cpu; ++cpu) {
        xtensa_mx_pic_update_cpu(mx, cpu);
    }
}

static void xtensa_mx_pic_ext_reg_write(void *opaque, hwaddr offset,
                                        uint64_t v, unsigned size)
{
    struct XtensaMxPicCpu *mx_cpu = opaque;
    struct XtensaMxPic *mx = mx_cpu->mx;
    unsigned cpu;

    if (offset < MIROUT + mx->n_irq) {
        mx->mirout[offset - MIROUT] = v;
        for (cpu = 0; cpu < mx->n_cpu; ++cpu) {
            uint32_t mask = 1u << (offset - MIROUT);

            if (!(mx->cpu[cpu].mirout_cache & mask) != !(v & (1u << cpu))) {
                mx->cpu[cpu].mirout_cache ^= mask;
                xtensa_mx_pic_update_cpu(mx, cpu);
            }
        }
    } else if (offset >= MIPICAUSE && offset < MIPICAUSE + mx->n_cpu) {
        cpu = offset - MIPICAUSE;
        mx->cpu[cpu].mipicause &= ~v;
        xtensa_mx_pic_update_cpu(mx, cpu);
    } else if (offset >= MIPISET && offset < MIPISET + 16) {
        for (cpu = 0; cpu < mx->n_cpu; ++cpu) {
            if (v & (1u << cpu)) {
                mx->cpu[cpu].mipicause |= 1u << (offset - MIPISET);
                xtensa_mx_pic_update_cpu(mx, cpu);
            }
        }
    } else {
        uint32_t change = 0;
        uint32_t oldv, newv;
        const char *name = "???";

        switch (offset) {
        case MIENG:
            change = mx->mieng & v;
            oldv = mx->mieng;
            mx->mieng &= ~v;
            newv = mx->mieng;
            name = "MIENG";
            break;

        case MIENGSET:
            change = ~mx->mieng & v;
            oldv = mx->mieng;
            mx->mieng |= v;
            newv = mx->mieng;
            name = "MIENG";
            break;

        case MIASG:
            change = mx->miasg & v;
            oldv = mx->miasg;
            mx->miasg &= ~v;
            newv = mx->miasg;
            name = "MIASG";
            break;

        case MIASGSET:
            change = ~mx->miasg & v;
            oldv = mx->miasg;
            mx->miasg |= v;
            newv = mx->miasg;
            name = "MIASG";
            break;

        case MIPIPART:
            change = mx->mipipart ^ v;
            oldv = mx->mipipart;
            mx->mipipart = v;
            newv = mx->mipipart;
            name = "MIPIPART";
            break;

        case MPSCORE:
            change = mx->runstall ^ v;
            oldv = mx->runstall;
            mx->runstall = v;
            newv = mx->runstall;
            name = "RUNSTALL";
            for (cpu = 0; cpu < mx->n_cpu; ++cpu) {
                if (change & (1u << cpu)) {
                    qemu_set_irq(mx->cpu[cpu].runstall, v & (1u << cpu));
                }
            }
            break;

        case CCON:
            mx_cpu->ccon = v & 0x1;
            break;

        default:
            qemu_log_mask(LOG_GUEST_ERROR,
                          "unknown WER in MX PIC range: 0x%08x = 0x%08x\n",
                          (uint32_t)offset, (uint32_t)v);
            break;
        }
        if (change) {
            qemu_log_mask(CPU_LOG_INT,
                          "%s: %s changed by CPU %d: %08x -> %08x\n",
                          __func__, name, (int)(mx_cpu - mx->cpu),
                          oldv, newv);
            xtensa_mx_pic_update_all(mx);
        }
    }
}

static const MemoryRegionOps xtensa_mx_pic_ops = {
    .read = xtensa_mx_pic_ext_reg_read,
    .write = xtensa_mx_pic_ext_reg_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
    .valid = {
        .unaligned = true,
    },
};

MemoryRegion *xtensa_mx_pic_register_cpu(XtensaMxPic *mx,
                                         qemu_irq *irq,
                                         qemu_irq runstall)
{
    struct XtensaMxPicCpu *mx_cpu = mx->cpu + mx->n_cpu;

    mx_cpu->mx = mx;
    mx_cpu->irq = irq;
    mx_cpu->runstall = runstall;

    memory_region_init_io(&mx_cpu->reg, NULL, &xtensa_mx_pic_ops, mx_cpu,
                          "mx_pic", 0x280);

    ++mx->n_cpu;
    return &mx_cpu->reg;
}

static void xtensa_mx_pic_set_irq(void *opaque, int irq, int active)
{
    XtensaMxPic *mx = opaque;

    if (irq < mx->n_irq) {
        uint32_t old_irq_state = mx->ext_irq_state;

        if (active) {
            mx->ext_irq_state |= 1u << irq;
        } else {
            mx->ext_irq_state &= ~(1u << irq);
        }
        if (old_irq_state != mx->ext_irq_state) {
            qemu_log_mask(CPU_LOG_INT,
                          "%s: IRQ %d, active: %d, ext_irq_state: %08x -> %08x\n",
                          __func__, irq, active,
                          old_irq_state, mx->ext_irq_state);
            xtensa_mx_pic_update_all(mx);
        }
    } else {
        qemu_log_mask(LOG_GUEST_ERROR, "%s: IRQ %d out of range\n",
                      __func__, irq);
    }
}

XtensaMxPic *xtensa_mx_pic_init(unsigned n_irq)
{
    XtensaMxPic *mx = calloc(1, sizeof(XtensaMxPic));

    mx->n_irq = n_irq + 1;
    mx->irq_inputs = qemu_allocate_irqs(xtensa_mx_pic_set_irq, mx,
                                        mx->n_irq);
    return mx;
}

void xtensa_mx_pic_reset(void *opaque)
{
    XtensaMxPic *mx = opaque;
    unsigned i;

    mx->ext_irq_state = 0;
    mx->mieng = mx->n_irq < 32 ? (1u << mx->n_irq) - 1 : ~0u;
    mx->miasg = 0;
    mx->mipipart = 0;
    for (i = 0; i < mx->n_irq; ++i) {
        mx->mirout[i] = 1;
    }
    for (i = 0; i < mx->n_cpu; ++i) {
        mx->cpu[i].mipicause = 0;
        mx->cpu[i].mirout_cache = i ? 0 : mx->mieng;
        mx->cpu[i].irq_state_cache = 0;
        mx->cpu[i].ccon = 0;
    }
    mx->runstall = (1u << mx->n_cpu) - 2;
    for (i = 0; i < mx->n_cpu; ++i) {
        qemu_set_irq(mx->cpu[i].runstall, i > 0);
    }
}

qemu_irq *xtensa_mx_pic_get_extints(XtensaMxPic *mx)
{
    return mx->irq_inputs + 1;
}
+26 −21
Original line number Diff line number Diff line
@@ -68,36 +68,37 @@ static void xtensa_set_irq(void *opaque, int irq, int active)
        uint32_t irq_bit = 1 << irq;

        if (active) {
            env->sregs[INTSET] |= irq_bit;
            atomic_or(&env->sregs[INTSET], irq_bit);
        } else if (env->config->interrupt[irq].inttype == INTTYPE_LEVEL) {
            env->sregs[INTSET] &= ~irq_bit;
            atomic_and(&env->sregs[INTSET], ~irq_bit);
        }

        check_interrupts(env);
    }
}

void xtensa_timer_irq(CPUXtensaState *env, uint32_t id, uint32_t active)
{
    qemu_set_irq(env->irq_inputs[env->config->timerint[id]], active);
}

static void xtensa_ccompare_cb(void *opaque)
{
    XtensaCcompareTimer *ccompare = opaque;
    CPUXtensaState *env = ccompare->env;
    unsigned i = ccompare - env->ccompare;

    xtensa_timer_irq(env, i, 1);
    qemu_set_irq(env->irq_inputs[env->config->timerint[i]], 1);
}

static void xtensa_set_runstall(void *opaque, int irq, int active)
{
    CPUXtensaState *env = opaque;
    xtensa_runstall(env, active);
}

void xtensa_irq_init(CPUXtensaState *env)
{
    env->irq_inputs = (void **)qemu_allocate_irqs(
            xtensa_set_irq, env, env->config->ninterrupt);
    if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
    unsigned i;

    env->irq_inputs = qemu_allocate_irqs(xtensa_set_irq, env,
                                         env->config->ninterrupt);
    if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
        env->time_base = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
        env->ccount_base = env->sregs[CCOUNT];
        for (i = 0; i < env->config->nccompare; ++i) {
@@ -106,16 +107,20 @@ void xtensa_irq_init(CPUXtensaState *env)
                    xtensa_ccompare_cb, env->ccompare + i);
        }
    }
    for (i = 0; i < env->config->nextint; ++i) {
        unsigned irq = env->config->extint[i];

        env->ext_irq_inputs[i] = env->irq_inputs[irq];
    }
    env->runstall_irq = qemu_allocate_irq(xtensa_set_runstall, env, 0);
}

void *xtensa_get_extint(CPUXtensaState *env, unsigned extint)
qemu_irq *xtensa_get_extints(CPUXtensaState *env)
{
    if (extint < env->config->nextint) {
        unsigned irq = env->config->extint[extint];
        return env->irq_inputs[irq];
    } else {
        qemu_log("%s: trying to acquire invalid external interrupt %d\n",
                __func__, extint);
        return NULL;
    return env->ext_irq_inputs;
}

qemu_irq xtensa_get_runstall(CPUXtensaState *env)
{
    return env->runstall_irq;
}
+48 −17
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@
#include "qemu/option.h"
#include "bootparam.h"
#include "xtensa_memory.h"
#include "hw/xtensa/mx_pic.h"

typedef struct XtfpgaFlashDesc {
    hwaddr base;
@@ -61,6 +62,7 @@ typedef struct XtfpgaBoardDesc {

typedef struct XtfpgaFpgaState {
    MemoryRegion iomem;
    uint32_t freq;
    uint32_t leds;
    uint32_t switches;
} XtfpgaFpgaState;
@@ -83,7 +85,7 @@ static uint64_t xtfpga_fpga_read(void *opaque, hwaddr addr,
        return 0x09272011;

    case 0x4: /*processor clock frequency, Hz*/
        return 10000000;
        return s->freq;

    case 0x8: /*LEDs (off = 0, on = 1)*/
        return s->leds;
@@ -119,13 +121,14 @@ static const MemoryRegionOps xtfpga_fpga_ops = {
};

static XtfpgaFpgaState *xtfpga_fpga_init(MemoryRegion *address_space,
        hwaddr base)
                                         hwaddr base, uint32_t freq)
{
    XtfpgaFpgaState *s = g_malloc(sizeof(XtfpgaFpgaState));

    memory_region_init_io(&s->iomem, NULL, &xtfpga_fpga_ops, s,
                          "xtfpga.fpga", 0x10000);
    memory_region_add_subregion(address_space, base, &s->iomem);
    s->freq = freq;
    xtfpga_fpga_reset(s);
    qemu_register_reset(xtfpga_fpga_reset, s);
    return s;
@@ -223,6 +226,8 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
    XtensaCPU *cpu = NULL;
    CPUXtensaState *env = NULL;
    MemoryRegion *system_io;
    XtensaMxPic *mx_pic = NULL;
    qemu_irq *extints;
    DriveInfo *dinfo;
    pflash_t *flash = NULL;
    QemuOpts *machine_opts = qemu_get_machine_opts();
@@ -231,19 +236,45 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
    const char *dtb_filename = qemu_opt_get(machine_opts, "dtb");
    const char *initrd_filename = qemu_opt_get(machine_opts, "initrd");
    const unsigned system_io_size = 224 * MiB;
    uint32_t freq = 10000000;
    int n;

    if (smp_cpus > 1) {
        mx_pic = xtensa_mx_pic_init(31);
        qemu_register_reset(xtensa_mx_pic_reset, mx_pic);
    }
    for (n = 0; n < smp_cpus; n++) {
        CPUXtensaState *cenv = NULL;

        cpu = XTENSA_CPU(cpu_create(machine->cpu_type));
        env = &cpu->env;
        cenv = &cpu->env;
        if (!env) {
            env = cenv;
            freq = env->config->clock_freq_khz * 1000;
        }

        if (mx_pic) {
            MemoryRegion *mx_eri;

        env->sregs[PRID] = n;
            mx_eri = xtensa_mx_pic_register_cpu(mx_pic,
                                                xtensa_get_extints(cenv),
                                                xtensa_get_runstall(cenv));
            memory_region_add_subregion(xtensa_get_er_region(cenv),
                                        0, mx_eri);
        }
        cenv->sregs[PRID] = n;
        xtensa_select_static_vectors(cenv, n != 0);
        qemu_register_reset(xtfpga_reset, cpu);
        /* Need MMU initialized prior to ELF loading,
         * so that ELF gets loaded into virtual addresses
         */
        cpu_reset(CPU(cpu));
    }
    if (smp_cpus > 1) {
        extints = xtensa_mx_pic_get_extints(mx_pic);
    } else {
        extints = xtensa_get_extints(env);
    }

    if (env) {
        XtensaMemory sysram = env->config->sysram;
@@ -272,13 +303,13 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
                                 system_io, 0, system_io_size);
        memory_region_add_subregion(system_memory, board->io[1], io);
    }
    xtfpga_fpga_init(system_io, 0x0d020000);
    xtfpga_fpga_init(system_io, 0x0d020000, freq);
    if (nd_table[0].used) {
        xtfpga_net_init(system_io, 0x0d030000, 0x0d030400, 0x0d800000,
                xtensa_get_extint(env, 1), nd_table);
                        extints[1], nd_table);
    }

    serial_mm_init(system_io, 0x0d050020, 2, xtensa_get_extint(env, 0),
    serial_mm_init(system_io, 0x0d050020, 2, extints[0],
                   115200, serial_hd(0), DEVICE_NATIVE_ENDIAN);

    dinfo = drive_get(IF_PFLASH, 0, 0);
@@ -568,7 +599,7 @@ static void xtfpga_lx60_class_init(ObjectClass *oc, void *data)

    mc->desc = "lx60 EVB (" XTENSA_DEFAULT_CPU_MODEL ")";
    mc->init = xtfpga_lx60_init;
    mc->max_cpus = 4;
    mc->max_cpus = 32;
    mc->default_cpu_type = XTENSA_DEFAULT_CPU_TYPE;
    mc->default_ram_size = 64 * MiB;
}
@@ -585,7 +616,7 @@ static void xtfpga_lx60_nommu_class_init(ObjectClass *oc, void *data)

    mc->desc = "lx60 noMMU EVB (" XTENSA_DEFAULT_CPU_NOMMU_MODEL ")";
    mc->init = xtfpga_lx60_nommu_init;
    mc->max_cpus = 4;
    mc->max_cpus = 32;
    mc->default_cpu_type = XTENSA_DEFAULT_CPU_NOMMU_TYPE;
    mc->default_ram_size = 64 * MiB;
}
@@ -602,7 +633,7 @@ static void xtfpga_lx200_class_init(ObjectClass *oc, void *data)

    mc->desc = "lx200 EVB (" XTENSA_DEFAULT_CPU_MODEL ")";
    mc->init = xtfpga_lx200_init;
    mc->max_cpus = 4;
    mc->max_cpus = 32;
    mc->default_cpu_type = XTENSA_DEFAULT_CPU_TYPE;
    mc->default_ram_size = 96 * MiB;
}
@@ -619,7 +650,7 @@ static void xtfpga_lx200_nommu_class_init(ObjectClass *oc, void *data)

    mc->desc = "lx200 noMMU EVB (" XTENSA_DEFAULT_CPU_NOMMU_MODEL ")";
    mc->init = xtfpga_lx200_nommu_init;
    mc->max_cpus = 4;
    mc->max_cpus = 32;
    mc->default_cpu_type = XTENSA_DEFAULT_CPU_NOMMU_TYPE;
    mc->default_ram_size = 96 * MiB;
}
@@ -636,7 +667,7 @@ static void xtfpga_ml605_class_init(ObjectClass *oc, void *data)

    mc->desc = "ml605 EVB (" XTENSA_DEFAULT_CPU_MODEL ")";
    mc->init = xtfpga_ml605_init;
    mc->max_cpus = 4;
    mc->max_cpus = 32;
    mc->default_cpu_type = XTENSA_DEFAULT_CPU_TYPE;
    mc->default_ram_size = 512 * MiB - XTFPGA_MMU_RESERVED_MEMORY_SIZE;
}
@@ -653,7 +684,7 @@ static void xtfpga_ml605_nommu_class_init(ObjectClass *oc, void *data)

    mc->desc = "ml605 noMMU EVB (" XTENSA_DEFAULT_CPU_NOMMU_MODEL ")";
    mc->init = xtfpga_ml605_nommu_init;
    mc->max_cpus = 4;
    mc->max_cpus = 32;
    mc->default_cpu_type = XTENSA_DEFAULT_CPU_NOMMU_TYPE;
    mc->default_ram_size = 256 * MiB;
}
@@ -670,7 +701,7 @@ static void xtfpga_kc705_class_init(ObjectClass *oc, void *data)

    mc->desc = "kc705 EVB (" XTENSA_DEFAULT_CPU_MODEL ")";
    mc->init = xtfpga_kc705_init;
    mc->max_cpus = 4;
    mc->max_cpus = 32;
    mc->default_cpu_type = XTENSA_DEFAULT_CPU_TYPE;
    mc->default_ram_size = 1 * GiB - XTFPGA_MMU_RESERVED_MEMORY_SIZE;
}
@@ -687,7 +718,7 @@ static void xtfpga_kc705_nommu_class_init(ObjectClass *oc, void *data)

    mc->desc = "kc705 noMMU EVB (" XTENSA_DEFAULT_CPU_NOMMU_MODEL ")";
    mc->init = xtfpga_kc705_nommu_init;
    mc->max_cpus = 4;
    mc->max_cpus = 32;
    mc->default_cpu_type = XTENSA_DEFAULT_CPU_NOMMU_TYPE;
    mc->default_ram_size = 256 * MiB;
}
+44 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013 - 2019, Max Filippov, Open Source and Linux Lab.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Open Source and Linux Lab nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _XTENSA_MX_PIC_H
#define _XTENSA_MX_PIC_H

#include "exec/memory.h"
#include "hw/irq.h"

struct XtensaMxPic;
typedef struct XtensaMxPic XtensaMxPic;

XtensaMxPic *xtensa_mx_pic_init(unsigned n_extint);
void xtensa_mx_pic_reset(void *opaque);
MemoryRegion *xtensa_mx_pic_register_cpu(XtensaMxPic *mx,
                                         qemu_irq *irq,
                                         qemu_irq runstall);
qemu_irq *xtensa_mx_pic_get_extints(XtensaMxPic *mx);

#endif
Loading