From: Anup Patel Date: Tue, 31 Aug 2021 11:06:00 +0000 (+0530) Subject: hw/intc: Rename sifive_clint sources to riscv_aclint sources X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=cc63a18282d8e8cd96d8bf26c29cad2e879ff9f6;p=qemu.git hw/intc: Rename sifive_clint sources to riscv_aclint sources We will be upgrading SiFive CLINT implementation into RISC-V ACLINT implementation so let's first rename the sources. Signed-off-by: Anup Patel Reviewed-by: Alistair Francis Reviewed-by: Bin Meng Message-id: 20210831110603.338681-2-anup.patel@wdc.com Signed-off-by: Alistair Francis --- diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig index f4694088a4..78aed93c45 100644 --- a/hw/intc/Kconfig +++ b/hw/intc/Kconfig @@ -62,7 +62,7 @@ config RX_ICU config LOONGSON_LIOINTC bool -config SIFIVE_CLINT +config RISCV_ACLINT bool config SIFIVE_PLIC diff --git a/hw/intc/meson.build b/hw/intc/meson.build index 4dcfea6aa8..a1d00aa48d 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -47,7 +47,7 @@ specific_ss.add(when: 'CONFIG_RX_ICU', if_true: files('rx_icu.c')) specific_ss.add(when: 'CONFIG_S390_FLIC', if_true: files('s390_flic.c')) specific_ss.add(when: 'CONFIG_S390_FLIC_KVM', if_true: files('s390_flic_kvm.c')) specific_ss.add(when: 'CONFIG_SH_INTC', if_true: files('sh_intc.c')) -specific_ss.add(when: 'CONFIG_SIFIVE_CLINT', if_true: files('sifive_clint.c')) +specific_ss.add(when: 'CONFIG_RISCV_ACLINT', if_true: files('riscv_aclint.c')) specific_ss.add(when: 'CONFIG_SIFIVE_PLIC', if_true: files('sifive_plic.c')) specific_ss.add(when: 'CONFIG_XICS', if_true: files('xics.c')) specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XICS'], diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c new file mode 100644 index 0000000000..31ce990d0e --- /dev/null +++ b/hw/intc/riscv_aclint.c @@ -0,0 +1,315 @@ +/* + * SiFive CLINT (Core Local Interruptor) + * + * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu + * Copyright (c) 2017 SiFive, Inc. + * + * This provides real-time clock, timer and interprocessor interrupts. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qemu/module.h" +#include "hw/sysbus.h" +#include "target/riscv/cpu.h" +#include "hw/qdev-properties.h" +#include "hw/intc/riscv_aclint.h" +#include "qemu/timer.h" +#include "hw/irq.h" + +typedef struct sifive_clint_callback { + SiFiveCLINTState *s; + int num; +} sifive_clint_callback; + +static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq) +{ + return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), + timebase_freq, NANOSECONDS_PER_SECOND); +} + +/* + * Called when timecmp is written to update the QEMU timer or immediately + * trigger timer interrupt if mtimecmp <= current timer value. + */ +static void sifive_clint_write_timecmp(SiFiveCLINTState *s, RISCVCPU *cpu, + int hartid, + uint64_t value, + uint32_t timebase_freq) +{ + uint64_t next; + uint64_t diff; + + uint64_t rtc_r = cpu_riscv_read_rtc(timebase_freq); + + cpu->env.timecmp = value; + if (cpu->env.timecmp <= rtc_r) { + /* if we're setting an MTIMECMP value in the "past", + immediately raise the timer interrupt */ + qemu_irq_raise(s->timer_irqs[hartid - s->hartid_base]); + return; + } + + /* otherwise, set up the future timer interrupt */ + qemu_irq_lower(s->timer_irqs[hartid - s->hartid_base]); + diff = cpu->env.timecmp - rtc_r; + /* back to ns (note args switched in muldiv64) */ + uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq); + + /* + * check if ns_diff overflowed and check if the addition would potentially + * overflow + */ + if ((NANOSECONDS_PER_SECOND > timebase_freq && ns_diff < diff) || + ns_diff > INT64_MAX) { + next = INT64_MAX; + } else { + /* + * as it is very unlikely qemu_clock_get_ns will return a value + * greater than INT64_MAX, no additional check is needed for an + * unsigned integer overflow. + */ + next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns_diff; + /* + * if ns_diff is INT64_MAX next may still be outside the range + * of a signed integer. + */ + next = MIN(next, INT64_MAX); + } + + timer_mod(cpu->env.timer, next); +} + +/* + * Callback used when the timer set using timer_mod expires. + * Should raise the timer interrupt line + */ +static void sifive_clint_timer_cb(void *opaque) +{ + sifive_clint_callback *state = opaque; + + qemu_irq_raise(state->s->timer_irqs[state->num]); +} + +/* CPU wants to read rtc or timecmp register */ +static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size) +{ + SiFiveCLINTState *clint = opaque; + if (addr >= clint->sip_base && + addr < clint->sip_base + (clint->num_harts << 2)) { + size_t hartid = clint->hartid_base + ((addr - clint->sip_base) >> 2); + CPUState *cpu = qemu_get_cpu(hartid); + CPURISCVState *env = cpu ? cpu->env_ptr : NULL; + if (!env) { + error_report("clint: invalid timecmp hartid: %zu", hartid); + } else if ((addr & 0x3) == 0) { + return (env->mip & MIP_MSIP) > 0; + } else { + error_report("clint: invalid read: %08x", (uint32_t)addr); + return 0; + } + } else if (addr >= clint->timecmp_base && + addr < clint->timecmp_base + (clint->num_harts << 3)) { + size_t hartid = clint->hartid_base + + ((addr - clint->timecmp_base) >> 3); + CPUState *cpu = qemu_get_cpu(hartid); + CPURISCVState *env = cpu ? cpu->env_ptr : NULL; + if (!env) { + error_report("clint: invalid timecmp hartid: %zu", hartid); + } else if ((addr & 0x7) == 0) { + /* timecmp_lo */ + uint64_t timecmp = env->timecmp; + return timecmp & 0xFFFFFFFF; + } else if ((addr & 0x7) == 4) { + /* timecmp_hi */ + uint64_t timecmp = env->timecmp; + return (timecmp >> 32) & 0xFFFFFFFF; + } else { + error_report("clint: invalid read: %08x", (uint32_t)addr); + return 0; + } + } else if (addr == clint->time_base) { + /* time_lo */ + return cpu_riscv_read_rtc(clint->timebase_freq) & 0xFFFFFFFF; + } else if (addr == clint->time_base + 4) { + /* time_hi */ + return (cpu_riscv_read_rtc(clint->timebase_freq) >> 32) & 0xFFFFFFFF; + } + + error_report("clint: invalid read: %08x", (uint32_t)addr); + return 0; +} + +/* CPU wrote to rtc or timecmp register */ +static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value, + unsigned size) +{ + SiFiveCLINTState *clint = opaque; + + if (addr >= clint->sip_base && + addr < clint->sip_base + (clint->num_harts << 2)) { + size_t hartid = clint->hartid_base + ((addr - clint->sip_base) >> 2); + CPUState *cpu = qemu_get_cpu(hartid); + CPURISCVState *env = cpu ? cpu->env_ptr : NULL; + if (!env) { + error_report("clint: invalid timecmp hartid: %zu", hartid); + } else if ((addr & 0x3) == 0) { + qemu_set_irq(clint->soft_irqs[hartid - clint->hartid_base], value); + } else { + error_report("clint: invalid sip write: %08x", (uint32_t)addr); + } + return; + } else if (addr >= clint->timecmp_base && + addr < clint->timecmp_base + (clint->num_harts << 3)) { + size_t hartid = clint->hartid_base + + ((addr - clint->timecmp_base) >> 3); + CPUState *cpu = qemu_get_cpu(hartid); + CPURISCVState *env = cpu ? cpu->env_ptr : NULL; + if (!env) { + error_report("clint: invalid timecmp hartid: %zu", hartid); + } else if ((addr & 0x7) == 0) { + /* timecmp_lo */ + uint64_t timecmp_hi = env->timecmp >> 32; + sifive_clint_write_timecmp(clint, RISCV_CPU(cpu), hartid, + timecmp_hi << 32 | (value & 0xFFFFFFFF), clint->timebase_freq); + return; + } else if ((addr & 0x7) == 4) { + /* timecmp_hi */ + uint64_t timecmp_lo = env->timecmp; + sifive_clint_write_timecmp(clint, RISCV_CPU(cpu), hartid, + value << 32 | (timecmp_lo & 0xFFFFFFFF), clint->timebase_freq); + } else { + error_report("clint: invalid timecmp write: %08x", (uint32_t)addr); + } + return; + } else if (addr == clint->time_base) { + /* time_lo */ + error_report("clint: time_lo write not implemented"); + return; + } else if (addr == clint->time_base + 4) { + /* time_hi */ + error_report("clint: time_hi write not implemented"); + return; + } + + error_report("clint: invalid write: %08x", (uint32_t)addr); +} + +static const MemoryRegionOps sifive_clint_ops = { + .read = sifive_clint_read, + .write = sifive_clint_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 8 + } +}; + +static Property sifive_clint_properties[] = { + DEFINE_PROP_UINT32("hartid-base", SiFiveCLINTState, hartid_base, 0), + DEFINE_PROP_UINT32("num-harts", SiFiveCLINTState, num_harts, 0), + DEFINE_PROP_UINT32("sip-base", SiFiveCLINTState, sip_base, 0), + DEFINE_PROP_UINT32("timecmp-base", SiFiveCLINTState, timecmp_base, 0), + DEFINE_PROP_UINT32("time-base", SiFiveCLINTState, time_base, 0), + DEFINE_PROP_UINT32("aperture-size", SiFiveCLINTState, aperture_size, 0), + DEFINE_PROP_UINT32("timebase-freq", SiFiveCLINTState, timebase_freq, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void sifive_clint_realize(DeviceState *dev, Error **errp) +{ + SiFiveCLINTState *s = SIFIVE_CLINT(dev); + memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_clint_ops, s, + TYPE_SIFIVE_CLINT, s->aperture_size); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); + + s->timer_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts); + qdev_init_gpio_out(dev, s->timer_irqs, s->num_harts); + + s->soft_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts); + qdev_init_gpio_out(dev, s->soft_irqs, s->num_harts); +} + +static void sifive_clint_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + dc->realize = sifive_clint_realize; + device_class_set_props(dc, sifive_clint_properties); +} + +static const TypeInfo sifive_clint_info = { + .name = TYPE_SIFIVE_CLINT, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SiFiveCLINTState), + .class_init = sifive_clint_class_init, +}; + +static void sifive_clint_register_types(void) +{ + type_register_static(&sifive_clint_info); +} + +type_init(sifive_clint_register_types) + +/* + * Create CLINT device. + */ +DeviceState *sifive_clint_create(hwaddr addr, hwaddr size, + uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base, + uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq, + bool provide_rdtime) +{ + int i; + + DeviceState *dev = qdev_new(TYPE_SIFIVE_CLINT); + qdev_prop_set_uint32(dev, "hartid-base", hartid_base); + qdev_prop_set_uint32(dev, "num-harts", num_harts); + qdev_prop_set_uint32(dev, "sip-base", sip_base); + qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base); + qdev_prop_set_uint32(dev, "time-base", time_base); + qdev_prop_set_uint32(dev, "aperture-size", size); + qdev_prop_set_uint32(dev, "timebase-freq", timebase_freq); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); + + for (i = 0; i < num_harts; i++) { + CPUState *cpu = qemu_get_cpu(hartid_base + i); + RISCVCPU *rvcpu = RISCV_CPU(cpu); + CPURISCVState *env = cpu ? cpu->env_ptr : NULL; + sifive_clint_callback *cb = g_malloc0(sizeof(sifive_clint_callback)); + + if (!env) { + g_free(cb); + continue; + } + if (provide_rdtime) { + riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, timebase_freq); + } + + cb->s = SIFIVE_CLINT(dev); + cb->num = i; + env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, + &sifive_clint_timer_cb, cb); + env->timecmp = 0; + + qdev_connect_gpio_out(dev, i, + qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_TIMER)); + qdev_connect_gpio_out(dev, num_harts + i, + qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_SOFT)); + } + + return dev; +} diff --git a/hw/intc/sifive_clint.c b/hw/intc/sifive_clint.c deleted file mode 100644 index ab172d8e40..0000000000 --- a/hw/intc/sifive_clint.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * SiFive CLINT (Core Local Interruptor) - * - * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu - * Copyright (c) 2017 SiFive, Inc. - * - * This provides real-time clock, timer and interprocessor interrupts. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2 or later, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "qemu/error-report.h" -#include "qemu/module.h" -#include "hw/sysbus.h" -#include "target/riscv/cpu.h" -#include "hw/qdev-properties.h" -#include "hw/intc/sifive_clint.h" -#include "qemu/timer.h" -#include "hw/irq.h" - -typedef struct sifive_clint_callback { - SiFiveCLINTState *s; - int num; -} sifive_clint_callback; - -static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq) -{ - return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - timebase_freq, NANOSECONDS_PER_SECOND); -} - -/* - * Called when timecmp is written to update the QEMU timer or immediately - * trigger timer interrupt if mtimecmp <= current timer value. - */ -static void sifive_clint_write_timecmp(SiFiveCLINTState *s, RISCVCPU *cpu, - int hartid, - uint64_t value, - uint32_t timebase_freq) -{ - uint64_t next; - uint64_t diff; - - uint64_t rtc_r = cpu_riscv_read_rtc(timebase_freq); - - cpu->env.timecmp = value; - if (cpu->env.timecmp <= rtc_r) { - /* if we're setting an MTIMECMP value in the "past", - immediately raise the timer interrupt */ - qemu_irq_raise(s->timer_irqs[hartid - s->hartid_base]); - return; - } - - /* otherwise, set up the future timer interrupt */ - qemu_irq_lower(s->timer_irqs[hartid - s->hartid_base]); - diff = cpu->env.timecmp - rtc_r; - /* back to ns (note args switched in muldiv64) */ - uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq); - - /* - * check if ns_diff overflowed and check if the addition would potentially - * overflow - */ - if ((NANOSECONDS_PER_SECOND > timebase_freq && ns_diff < diff) || - ns_diff > INT64_MAX) { - next = INT64_MAX; - } else { - /* - * as it is very unlikely qemu_clock_get_ns will return a value - * greater than INT64_MAX, no additional check is needed for an - * unsigned integer overflow. - */ - next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns_diff; - /* - * if ns_diff is INT64_MAX next may still be outside the range - * of a signed integer. - */ - next = MIN(next, INT64_MAX); - } - - timer_mod(cpu->env.timer, next); -} - -/* - * Callback used when the timer set using timer_mod expires. - * Should raise the timer interrupt line - */ -static void sifive_clint_timer_cb(void *opaque) -{ - sifive_clint_callback *state = opaque; - - qemu_irq_raise(state->s->timer_irqs[state->num]); -} - -/* CPU wants to read rtc or timecmp register */ -static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size) -{ - SiFiveCLINTState *clint = opaque; - if (addr >= clint->sip_base && - addr < clint->sip_base + (clint->num_harts << 2)) { - size_t hartid = clint->hartid_base + ((addr - clint->sip_base) >> 2); - CPUState *cpu = qemu_get_cpu(hartid); - CPURISCVState *env = cpu ? cpu->env_ptr : NULL; - if (!env) { - error_report("clint: invalid timecmp hartid: %zu", hartid); - } else if ((addr & 0x3) == 0) { - return (env->mip & MIP_MSIP) > 0; - } else { - error_report("clint: invalid read: %08x", (uint32_t)addr); - return 0; - } - } else if (addr >= clint->timecmp_base && - addr < clint->timecmp_base + (clint->num_harts << 3)) { - size_t hartid = clint->hartid_base + - ((addr - clint->timecmp_base) >> 3); - CPUState *cpu = qemu_get_cpu(hartid); - CPURISCVState *env = cpu ? cpu->env_ptr : NULL; - if (!env) { - error_report("clint: invalid timecmp hartid: %zu", hartid); - } else if ((addr & 0x7) == 0) { - /* timecmp_lo */ - uint64_t timecmp = env->timecmp; - return timecmp & 0xFFFFFFFF; - } else if ((addr & 0x7) == 4) { - /* timecmp_hi */ - uint64_t timecmp = env->timecmp; - return (timecmp >> 32) & 0xFFFFFFFF; - } else { - error_report("clint: invalid read: %08x", (uint32_t)addr); - return 0; - } - } else if (addr == clint->time_base) { - /* time_lo */ - return cpu_riscv_read_rtc(clint->timebase_freq) & 0xFFFFFFFF; - } else if (addr == clint->time_base + 4) { - /* time_hi */ - return (cpu_riscv_read_rtc(clint->timebase_freq) >> 32) & 0xFFFFFFFF; - } - - error_report("clint: invalid read: %08x", (uint32_t)addr); - return 0; -} - -/* CPU wrote to rtc or timecmp register */ -static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ - SiFiveCLINTState *clint = opaque; - - if (addr >= clint->sip_base && - addr < clint->sip_base + (clint->num_harts << 2)) { - size_t hartid = clint->hartid_base + ((addr - clint->sip_base) >> 2); - CPUState *cpu = qemu_get_cpu(hartid); - CPURISCVState *env = cpu ? cpu->env_ptr : NULL; - if (!env) { - error_report("clint: invalid timecmp hartid: %zu", hartid); - } else if ((addr & 0x3) == 0) { - qemu_set_irq(clint->soft_irqs[hartid - clint->hartid_base], value); - } else { - error_report("clint: invalid sip write: %08x", (uint32_t)addr); - } - return; - } else if (addr >= clint->timecmp_base && - addr < clint->timecmp_base + (clint->num_harts << 3)) { - size_t hartid = clint->hartid_base + - ((addr - clint->timecmp_base) >> 3); - CPUState *cpu = qemu_get_cpu(hartid); - CPURISCVState *env = cpu ? cpu->env_ptr : NULL; - if (!env) { - error_report("clint: invalid timecmp hartid: %zu", hartid); - } else if ((addr & 0x7) == 0) { - /* timecmp_lo */ - uint64_t timecmp_hi = env->timecmp >> 32; - sifive_clint_write_timecmp(clint, RISCV_CPU(cpu), hartid, - timecmp_hi << 32 | (value & 0xFFFFFFFF), clint->timebase_freq); - return; - } else if ((addr & 0x7) == 4) { - /* timecmp_hi */ - uint64_t timecmp_lo = env->timecmp; - sifive_clint_write_timecmp(clint, RISCV_CPU(cpu), hartid, - value << 32 | (timecmp_lo & 0xFFFFFFFF), clint->timebase_freq); - } else { - error_report("clint: invalid timecmp write: %08x", (uint32_t)addr); - } - return; - } else if (addr == clint->time_base) { - /* time_lo */ - error_report("clint: time_lo write not implemented"); - return; - } else if (addr == clint->time_base + 4) { - /* time_hi */ - error_report("clint: time_hi write not implemented"); - return; - } - - error_report("clint: invalid write: %08x", (uint32_t)addr); -} - -static const MemoryRegionOps sifive_clint_ops = { - .read = sifive_clint_read, - .write = sifive_clint_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 8 - } -}; - -static Property sifive_clint_properties[] = { - DEFINE_PROP_UINT32("hartid-base", SiFiveCLINTState, hartid_base, 0), - DEFINE_PROP_UINT32("num-harts", SiFiveCLINTState, num_harts, 0), - DEFINE_PROP_UINT32("sip-base", SiFiveCLINTState, sip_base, 0), - DEFINE_PROP_UINT32("timecmp-base", SiFiveCLINTState, timecmp_base, 0), - DEFINE_PROP_UINT32("time-base", SiFiveCLINTState, time_base, 0), - DEFINE_PROP_UINT32("aperture-size", SiFiveCLINTState, aperture_size, 0), - DEFINE_PROP_UINT32("timebase-freq", SiFiveCLINTState, timebase_freq, 0), - DEFINE_PROP_END_OF_LIST(), -}; - -static void sifive_clint_realize(DeviceState *dev, Error **errp) -{ - SiFiveCLINTState *s = SIFIVE_CLINT(dev); - memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_clint_ops, s, - TYPE_SIFIVE_CLINT, s->aperture_size); - sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); - - s->timer_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts); - qdev_init_gpio_out(dev, s->timer_irqs, s->num_harts); - - s->soft_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts); - qdev_init_gpio_out(dev, s->soft_irqs, s->num_harts); -} - -static void sifive_clint_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - dc->realize = sifive_clint_realize; - device_class_set_props(dc, sifive_clint_properties); -} - -static const TypeInfo sifive_clint_info = { - .name = TYPE_SIFIVE_CLINT, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SiFiveCLINTState), - .class_init = sifive_clint_class_init, -}; - -static void sifive_clint_register_types(void) -{ - type_register_static(&sifive_clint_info); -} - -type_init(sifive_clint_register_types) - -/* - * Create CLINT device. - */ -DeviceState *sifive_clint_create(hwaddr addr, hwaddr size, - uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base, - uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq, - bool provide_rdtime) -{ - int i; - - DeviceState *dev = qdev_new(TYPE_SIFIVE_CLINT); - qdev_prop_set_uint32(dev, "hartid-base", hartid_base); - qdev_prop_set_uint32(dev, "num-harts", num_harts); - qdev_prop_set_uint32(dev, "sip-base", sip_base); - qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base); - qdev_prop_set_uint32(dev, "time-base", time_base); - qdev_prop_set_uint32(dev, "aperture-size", size); - qdev_prop_set_uint32(dev, "timebase-freq", timebase_freq); - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); - - for (i = 0; i < num_harts; i++) { - CPUState *cpu = qemu_get_cpu(hartid_base + i); - RISCVCPU *rvcpu = RISCV_CPU(cpu); - CPURISCVState *env = cpu ? cpu->env_ptr : NULL; - sifive_clint_callback *cb = g_malloc0(sizeof(sifive_clint_callback)); - - if (!env) { - g_free(cb); - continue; - } - if (provide_rdtime) { - riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, timebase_freq); - } - - cb->s = SIFIVE_CLINT(dev); - cb->num = i; - env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, - &sifive_clint_timer_cb, cb); - env->timecmp = 0; - - qdev_connect_gpio_out(dev, i, - qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_TIMER)); - qdev_connect_gpio_out(dev, num_harts + i, - qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_SOFT)); - } - - return dev; -} diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index d56c339ef6..d2d869aaad 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -12,7 +12,7 @@ config MICROCHIP_PFSOC select MCHP_PFSOC_MMUART select MCHP_PFSOC_SYSREG select MSI_NONBROKEN - select SIFIVE_CLINT + select RISCV_ACLINT select SIFIVE_PDMA select SIFIVE_PLIC select UNIMP @@ -26,7 +26,7 @@ config SHAKTI_C bool select UNIMP select SHAKTI_UART - select SIFIVE_CLINT + select RISCV_ACLINT select SIFIVE_PLIC config RISCV_VIRT @@ -41,7 +41,7 @@ config RISCV_VIRT select PCI_EXPRESS_GENERIC_BRIDGE select PFLASH_CFI01 select SERIAL - select SIFIVE_CLINT + select RISCV_ACLINT select SIFIVE_PLIC select SIFIVE_TEST select VIRTIO_MMIO @@ -50,7 +50,7 @@ config RISCV_VIRT config SIFIVE_E bool select MSI_NONBROKEN - select SIFIVE_CLINT + select RISCV_ACLINT select SIFIVE_GPIO select SIFIVE_PLIC select SIFIVE_UART @@ -61,7 +61,7 @@ config SIFIVE_U bool select CADENCE select MSI_NONBROKEN - select SIFIVE_CLINT + select RISCV_ACLINT select SIFIVE_GPIO select SIFIVE_PDMA select SIFIVE_PLIC @@ -79,5 +79,5 @@ config SPIKE select RISCV_NUMA select HTIF select MSI_NONBROKEN - select SIFIVE_CLINT + select RISCV_ACLINT select SIFIVE_PLIC diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c index eef55f69fd..eed9e81355 100644 --- a/hw/riscv/microchip_pfsoc.c +++ b/hw/riscv/microchip_pfsoc.c @@ -49,7 +49,7 @@ #include "hw/riscv/boot.h" #include "hw/riscv/riscv_hart.h" #include "hw/riscv/microchip_pfsoc.h" -#include "hw/intc/sifive_clint.h" +#include "hw/intc/riscv_aclint.h" #include "hw/intc/sifive_plic.h" #include "sysemu/device_tree.h" #include "sysemu/sysemu.h" diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c index 09d4e1433e..f9f0a45651 100644 --- a/hw/riscv/shakti_c.c +++ b/hw/riscv/shakti_c.c @@ -21,7 +21,7 @@ #include "hw/riscv/shakti_c.h" #include "qapi/error.h" #include "hw/intc/sifive_plic.h" -#include "hw/intc/sifive_clint.h" +#include "hw/intc/riscv_aclint.h" #include "sysemu/sysemu.h" #include "hw/qdev-properties.h" #include "exec/address-spaces.h" diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index 04265c5640..a73848958e 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -41,7 +41,7 @@ #include "hw/riscv/sifive_e.h" #include "hw/riscv/boot.h" #include "hw/char/sifive_uart.h" -#include "hw/intc/sifive_clint.h" +#include "hw/intc/riscv_aclint.h" #include "hw/intc/sifive_plic.h" #include "hw/misc/sifive_e_prci.h" #include "chardev/char.h" diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index f4cde10667..aaab46c43c 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -52,7 +52,7 @@ #include "hw/riscv/sifive_u.h" #include "hw/riscv/boot.h" #include "hw/char/sifive_uart.h" -#include "hw/intc/sifive_clint.h" +#include "hw/intc/riscv_aclint.h" #include "hw/intc/sifive_plic.h" #include "chardev/char.h" #include "net/eth.h" diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index aae36f2cb4..690c19c12a 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -35,7 +35,7 @@ #include "hw/riscv/boot.h" #include "hw/riscv/numa.h" #include "hw/char/riscv_htif.h" -#include "hw/intc/sifive_clint.h" +#include "hw/intc/riscv_aclint.h" #include "chardev/char.h" #include "sysemu/device_tree.h" #include "sysemu/sysemu.h" diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 47f1beb473..df33fd74c2 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -32,7 +32,7 @@ #include "hw/riscv/virt.h" #include "hw/riscv/boot.h" #include "hw/riscv/numa.h" -#include "hw/intc/sifive_clint.h" +#include "hw/intc/riscv_aclint.h" #include "hw/intc/sifive_plic.h" #include "hw/misc/sifive_test.h" #include "chardev/char.h" diff --git a/include/hw/intc/riscv_aclint.h b/include/hw/intc/riscv_aclint.h new file mode 100644 index 0000000000..921b1561dd --- /dev/null +++ b/include/hw/intc/riscv_aclint.h @@ -0,0 +1,62 @@ +/* + * SiFive CLINT (Core Local Interruptor) interface + * + * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu + * Copyright (c) 2017 SiFive, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#ifndef HW_SIFIVE_CLINT_H +#define HW_SIFIVE_CLINT_H + +#include "hw/sysbus.h" + +#define TYPE_SIFIVE_CLINT "riscv.sifive.clint" + +#define SIFIVE_CLINT(obj) \ + OBJECT_CHECK(SiFiveCLINTState, (obj), TYPE_SIFIVE_CLINT) + +typedef struct SiFiveCLINTState { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion mmio; + uint32_t hartid_base; + uint32_t num_harts; + uint32_t sip_base; + uint32_t timecmp_base; + uint32_t time_base; + uint32_t aperture_size; + uint32_t timebase_freq; + qemu_irq *timer_irqs; + qemu_irq *soft_irqs; +} SiFiveCLINTState; + +DeviceState *sifive_clint_create(hwaddr addr, hwaddr size, + uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base, + uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq, + bool provide_rdtime); + +enum { + SIFIVE_SIP_BASE = 0x0, + SIFIVE_TIMECMP_BASE = 0x4000, + SIFIVE_TIME_BASE = 0xBFF8 +}; + +enum { + SIFIVE_CLINT_TIMEBASE_FREQ = 10000000 +}; + +#endif diff --git a/include/hw/intc/sifive_clint.h b/include/hw/intc/sifive_clint.h deleted file mode 100644 index 921b1561dd..0000000000 --- a/include/hw/intc/sifive_clint.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * SiFive CLINT (Core Local Interruptor) interface - * - * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu - * Copyright (c) 2017 SiFive, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2 or later, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#ifndef HW_SIFIVE_CLINT_H -#define HW_SIFIVE_CLINT_H - -#include "hw/sysbus.h" - -#define TYPE_SIFIVE_CLINT "riscv.sifive.clint" - -#define SIFIVE_CLINT(obj) \ - OBJECT_CHECK(SiFiveCLINTState, (obj), TYPE_SIFIVE_CLINT) - -typedef struct SiFiveCLINTState { - /*< private >*/ - SysBusDevice parent_obj; - - /*< public >*/ - MemoryRegion mmio; - uint32_t hartid_base; - uint32_t num_harts; - uint32_t sip_base; - uint32_t timecmp_base; - uint32_t time_base; - uint32_t aperture_size; - uint32_t timebase_freq; - qemu_irq *timer_irqs; - qemu_irq *soft_irqs; -} SiFiveCLINTState; - -DeviceState *sifive_clint_create(hwaddr addr, hwaddr size, - uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base, - uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq, - bool provide_rdtime); - -enum { - SIFIVE_SIP_BASE = 0x0, - SIFIVE_TIMECMP_BASE = 0x4000, - SIFIVE_TIME_BASE = 0xBFF8 -}; - -enum { - SIFIVE_CLINT_TIMEBASE_FREQ = 10000000 -}; - -#endif