* [Qemu-devel] [PATCH v3 0/5][RFC] New SPARC machine: Leon3 @ 2011-01-21 17:00 Fabien Chouteau 2011-01-21 17:00 ` [Qemu-devel] [PATCH v3 1/5] SPARC: Emulation of GRLIB GPTimer Fabien Chouteau 2011-01-21 19:04 ` [Qemu-devel] [PATCH v3 0/5][RFC] New SPARC machine: Leon3 Blue Swirl 0 siblings, 2 replies; 10+ messages in thread From: Fabien Chouteau @ 2011-01-21 17:00 UTC (permalink / raw) To: qemu-devel; +Cc: Fabien Chouteau Hello Qemu-devel, Here is the third version of Leon3 emulation patch-set. Modifications since v2: - Tracepoints - DEFINE_PROP_* macros - New interface to trigger interrupts on Leon3 (set_pil_in:leon3.c) - Minor reformating Please feel free to comment. Regards, ------------------------------------------------------------------------------- This patch set introduces a new SPARC V8 machine: Leon3. It's an open-source VHDL System-On-Chip, well known in space industry (more information on http://www.gaisler.com). Leon3 is made of multiple components available in the GrLib VHDL library. Three devices are implemented: uart, timers and IRQ manager. You can find code for these peripherals in the grlib_* files. Modifications have been done to the SPARC cpu emulation code to handle Leon3's specific behavior: - IRQ management - Cache control - Asr17 (implementation-dependent Ancillary State Registers) - Shutdown Fabien Chouteau (5): SPARC: Emulation of GRLIB GPTimer SPARC: Emulation of GRLIB IRQMP SPARC: Emulation of GRLIB APB UART SPARC: Emulation of Leon3 SPARC: Add asr17 register support Makefile.target | 5 +- hw/grlib.h | 126 +++++++++++++++ hw/grlib_apbuart.c | 189 ++++++++++++++++++++++ hw/grlib_gptimer.c | 401 ++++++++++++++++++++++++++++++++++++++++++++++ hw/grlib_irqmp.c | 380 +++++++++++++++++++++++++++++++++++++++++++ hw/leon3.c | 231 ++++++++++++++++++++++++++ target-sparc/cpu.h | 38 +++-- target-sparc/helper.c | 8 +- target-sparc/helper.h | 1 + target-sparc/op_helper.c | 154 +++++++++++++++++- target-sparc/translate.c | 24 +++- trace-events | 20 +++ 12 files changed, 1555 insertions(+), 22 deletions(-) create mode 100644 hw/grlib.h create mode 100644 hw/grlib_apbuart.c create mode 100644 hw/grlib_gptimer.c create mode 100644 hw/grlib_irqmp.c create mode 100644 hw/leon3.c ^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH v3 1/5] SPARC: Emulation of GRLIB GPTimer 2011-01-21 17:00 [Qemu-devel] [PATCH v3 0/5][RFC] New SPARC machine: Leon3 Fabien Chouteau @ 2011-01-21 17:00 ` Fabien Chouteau 2011-01-21 17:00 ` [Qemu-devel] [PATCH v3 2/5] SPARC: Emulation of GRLIB IRQMP Fabien Chouteau 2011-01-21 19:04 ` [Qemu-devel] [PATCH v3 0/5][RFC] New SPARC machine: Leon3 Blue Swirl 1 sibling, 1 reply; 10+ messages in thread From: Fabien Chouteau @ 2011-01-21 17:00 UTC (permalink / raw) To: qemu-devel; +Cc: Fabien Chouteau This device exposes three parameters: - frequency (uint32) : The system frequency - irq-line (uint32) : IRQ line number for the first timer (others use irq-line + 1, irq-line + 2...) - nr-timers (uint32) : Number of timers Emulation of GrLib devices is base on the GRLIB IP Core User's Manual: http://www.gaisler.com/products/grlib/grip.pdf Signed-off-by: Fabien Chouteau <chouteau@adacore.com> --- hw/grlib.h | 65 +++++++++ hw/grlib_gptimer.c | 401 ++++++++++++++++++++++++++++++++++++++++++++++++++++ trace-events | 10 ++ 3 files changed, 476 insertions(+), 0 deletions(-) diff --git a/hw/grlib.h b/hw/grlib.h new file mode 100644 index 0000000..776acf9 --- /dev/null +++ b/hw/grlib.h @@ -0,0 +1,65 @@ +/* + * QEMU GRLIB Components + * + * Copyright (c) 2010-2011 AdaCore + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef _GRLIB_H_ +#define _GRLIB_H_ + +#include "qdev.h" +#include "sysbus.h" + +/* Emulation of GrLib device is base on the GRLIB IP Core User's Manual: + * http://www.gaisler.com/products/grlib/grip.pdf + */ + +/* GPTimer */ + +static inline +DeviceState *grlib_gptimer_create(target_phys_addr_t base, + uint32_t nr_timers, + uint32_t freq, + qemu_irq *cpu_irqs, + int base_irq) +{ + DeviceState *dev; + int i; + + dev = qdev_create(NULL, "grlib,gptimer"); + qdev_prop_set_uint32(dev, "nr-timers", nr_timers); + qdev_prop_set_uint32(dev, "frequency", freq); + qdev_prop_set_uint32(dev, "irq-line", base_irq); + + if (qdev_init(dev)) { + return NULL; + } + + sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); + + for (i = 0; i < nr_timers; i++) { + sysbus_connect_irq(sysbus_from_qdev(dev), i, cpu_irqs[base_irq + i]); + } + + return dev; +} + +#endif /* ! _GRLIB_H_ */ diff --git a/hw/grlib_gptimer.c b/hw/grlib_gptimer.c new file mode 100644 index 0000000..43661d3 --- /dev/null +++ b/hw/grlib_gptimer.c @@ -0,0 +1,401 @@ +/* + * QEMU GRLIB GPTimer Emulator + * + * Copyright (c) 2010-2011 AdaCore + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "sysbus.h" +#include "qemu-timer.h" + +#include "trace.h" + +#define UNIT_REG_SIZE 16 /* Size of memory mapped regs for the unit */ +#define GPTIMER_REG_SIZE 16 /* Size of memory mapped regs for a GPTimer */ + +#define GPTIMER_MAX_TIMERS 8 + +/* GPTimer Config register fields */ +#define GPTIMER_ENABLE (1 << 0) +#define GPTIMER_RESTART (1 << 1) +#define GPTIMER_LOAD (1 << 2) +#define GPTIMER_INT_ENABLE (1 << 3) +#define GPTIMER_INT_PENDING (1 << 4) +#define GPTIMER_CHAIN (1 << 5) /* Not supported */ +#define GPTIMER_DEBUG_HALT (1 << 6) /* Not supported */ + +/* Memory mapped register offsets */ +#define SCALER_OFFSET 0x00 +#define SCALER_RELOAD_OFFSET 0x04 +#define CONFIG_OFFSET 0x08 +#define COUNTER_OFFSET 0x00 +#define COUNTER_RELOAD_OFFSET 0x04 +#define TIMER_BASE 0x10 + +typedef struct GPTimer GPTimer; +typedef struct GPTimerUnit GPTimerUnit; + +struct GPTimer +{ + QEMUBH *bh; + struct ptimer_state *ptimer; + + qemu_irq irq; + int id; + GPTimerUnit *unit; + + /* registers */ + uint32_t counter; + uint32_t reload; + uint32_t config; +}; + +struct GPTimerUnit +{ + SysBusDevice busdev; + + uint32_t nr_timers; /* Number of timers available */ + uint32_t freq_hz; /* System frequency */ + uint32_t irq_line; /* Base irq line */ + + GPTimer *timers; + + /* registers */ + uint32_t scaler; + uint32_t reload; + uint32_t config; +}; + +static void grlib_gptimer_enable(GPTimer *timer) +{ + assert(timer != NULL); + + + ptimer_stop(timer->ptimer); + + if (!(timer->config & GPTIMER_ENABLE)) { + /* Timer disabled */ + trace_grlib_gptimer_disabled(timer->id, timer->config); + return; + } + + /* ptimer is triggered when the counter reach 0 but GPTimer is triggered at + underflow. Set count + 1 to simulate the GPTimer behavior. */ + + trace_grlib_gptimer_enable(timer->id, timer->counter + 1); + + ptimer_set_count(timer->ptimer, timer->counter + 1); + ptimer_run(timer->ptimer, 1); +} + +static void grlib_gptimer_restart(GPTimer *timer) +{ + assert(timer != NULL); + + trace_grlib_gptimer_restart(timer->id, timer->reload); + + timer->counter = timer->reload; + grlib_gptimer_enable(timer); +} + +static void grlib_gptimer_set_scaler(GPTimerUnit *unit, uint32_t scaler) +{ + int i = 0; + uint32_t value = 0; + + assert(unit != NULL); + + if (scaler > 0) { + value = unit->freq_hz / (scaler + 1); + } else { + value = unit->freq_hz; + } + + trace_grlib_gptimer_set_scaler(scaler, value); + + for (i = 0; i < unit->nr_timers; i++) { + ptimer_set_freq(unit->timers[i].ptimer, value); + } +} + +static void grlib_gptimer_hit(void *opaque) +{ + GPTimer *timer = opaque; + assert(timer != NULL); + + trace_grlib_gptimer_hit(timer->id); + + /* Timer expired */ + + if (timer->config & GPTIMER_INT_ENABLE) { + /* Set the pending bit (only unset by write in the config register) */ + timer->config |= GPTIMER_INT_PENDING; + qemu_irq_pulse(timer->irq); + } + + if (timer->config & GPTIMER_RESTART) { + grlib_gptimer_restart(timer); + } +} + +static uint32_t grlib_gptimer_readl(void *opaque, target_phys_addr_t addr) +{ + GPTimerUnit *unit = opaque; + target_phys_addr_t timer_addr; + int id; + uint32_t value = 0; + + addr &= 0xff; + + /* Unit registers */ + switch (addr) + { + case SCALER_OFFSET: + trace_grlib_gptimer_readl(-1, "scaler:", unit->scaler); + return unit->scaler; + + case SCALER_RELOAD_OFFSET: + trace_grlib_gptimer_readl(-1, "reload:", unit->reload); + return unit->reload; + + case CONFIG_OFFSET: + trace_grlib_gptimer_readl(-1, "config:", unit->config); + return unit->config; + + default: + break; + } + + timer_addr = (addr % TIMER_BASE); + id = (addr - TIMER_BASE) / TIMER_BASE; + + if (id >= 0 && id < unit->nr_timers) { + + /* GPTimer registers */ + switch (timer_addr) + { + case COUNTER_OFFSET: + value = ptimer_get_count (unit->timers[id].ptimer); + trace_grlib_gptimer_readl(id, "counter value:", value); + return value; + + case COUNTER_RELOAD_OFFSET: + value = unit->timers[id].reload; + trace_grlib_gptimer_readl(id, "reload value:", value); + return value; + + case CONFIG_OFFSET: + trace_grlib_gptimer_readl(id, "scaler value:", + unit->timers[id].config); + return unit->timers[id].config; + + default: + break; + } + + } + + trace_grlib_gptimer_unknown_register("read", addr); + return 0; +} + +static void +grlib_gptimer_writel(void *opaque, target_phys_addr_t addr, uint32_t value) +{ + GPTimerUnit *unit = opaque; + target_phys_addr_t timer_addr; + int id; + + addr &= 0xff; + + /* Unit registers */ + switch (addr) + { + case SCALER_OFFSET: + value &= 0xFFFF; /* clean up the value */ + unit->scaler = value; + trace_grlib_gptimer_writel(-1, "scaler:", unit->scaler); + return; + + case SCALER_RELOAD_OFFSET: + value &= 0xFFFF; /* clean up the value */ + unit->reload = value; + trace_grlib_gptimer_writel(-1, "reload:", unit->reload); + grlib_gptimer_set_scaler(unit, value); + return; + + case CONFIG_OFFSET: + /* Read Only (disable timer freeze not supported) */ + trace_grlib_gptimer_writel(-1, "config (Read Only):", 0); + return; + + default: + break; + } + + timer_addr = (addr % TIMER_BASE); + id = (addr - TIMER_BASE) / TIMER_BASE; + + if (id >= 0 && id < unit->nr_timers) { + + /* GPTimer registers */ + switch (timer_addr) + { + case COUNTER_OFFSET: + trace_grlib_gptimer_writel(id, "counter:", value); + unit->timers[id].counter = value; + grlib_gptimer_enable(&unit->timers[id]); + return; + + case COUNTER_RELOAD_OFFSET: + trace_grlib_gptimer_writel(id, "reload:", value); + unit->timers[id].reload = value; + return; + + case CONFIG_OFFSET: + trace_grlib_gptimer_writel(id, "config:", value); + + if (value & GPTIMER_INT_PENDING) { + /* clear pending bit */ + value &= ~GPTIMER_INT_PENDING; + } else { + /* keep pending bit */ + value |= unit->timers[id].config & GPTIMER_INT_PENDING; + } + + unit->timers[id].config = value; + + /* gptimer_restart calls gptimer_enable, so if "enable" and + "load" bits are present, we just have to call restart. */ + + if (value & GPTIMER_LOAD) { + grlib_gptimer_restart(&unit->timers[id]); + } else if (value & GPTIMER_ENABLE) { + grlib_gptimer_enable(&unit->timers[id]); + } + + /* These fields must always be read as 0 */ + value &= ~(GPTIMER_LOAD & GPTIMER_DEBUG_HALT); + + unit->timers[id].config = value; + return; + + default: + break; + } + + } + + trace_grlib_gptimer_unknown_register("write", addr); +} + +static CPUReadMemoryFunc * const grlib_gptimer_read[] = { + NULL, NULL, grlib_gptimer_readl, +}; + +static CPUWriteMemoryFunc * const grlib_gptimer_write[] = { + NULL, NULL, grlib_gptimer_writel, +}; + +static void grlib_gptimer_reset(DeviceState *d) +{ + GPTimerUnit *unit = container_of(d, GPTimerUnit, busdev.qdev); + int i = 0; + + assert(unit != NULL); + + unit->scaler = 0; + unit->reload = 0; + unit->config = 0; + + unit->config = unit->nr_timers; + unit->config |= unit->irq_line << 3; + unit->config |= 1 << 8; /* separate interrupt */ + unit->config |= 1 << 9; /* Disable timer freeze */ + + + for (i = 0; i < unit->nr_timers; i++) { + GPTimer *timer = &unit->timers[i]; + + timer->counter = 0; + timer->reload = 0; + timer->config = 0; + ptimer_stop(timer->ptimer); + ptimer_set_count(timer->ptimer, 0); + ptimer_set_freq(timer->ptimer, unit->freq_hz); + } +} + +static int grlib_gptimer_init(SysBusDevice *dev) +{ + GPTimerUnit *unit = FROM_SYSBUS(typeof (*unit), dev); + unsigned int i; + int timer_regs; + + assert(unit->nr_timers > 0); + assert(unit->nr_timers <= GPTIMER_MAX_TIMERS); + + unit->timers = qemu_mallocz(sizeof unit->timers[0] * unit->nr_timers); + + for (i = 0; i < unit->nr_timers; i++) { + GPTimer *timer = &unit->timers[i]; + + timer->unit = unit; + timer->bh = qemu_bh_new(grlib_gptimer_hit, timer); + timer->ptimer = ptimer_init(timer->bh); + timer->id = i; + + /* One IRQ line for each timer */ + sysbus_init_irq(dev, &timer->irq); + + ptimer_set_freq(timer->ptimer, unit->freq_hz); + } + + timer_regs = cpu_register_io_memory(grlib_gptimer_read, + grlib_gptimer_write, + unit, DEVICE_NATIVE_ENDIAN); + if (timer_regs < 0) { + return -1; + } + + sysbus_init_mmio(dev, UNIT_REG_SIZE + GPTIMER_REG_SIZE * unit->nr_timers, + timer_regs); + return 0; +} + +static SysBusDeviceInfo grlib_gptimer_info = { + .init = grlib_gptimer_init, + .qdev.name = "grlib,gptimer", + .qdev.reset = grlib_gptimer_reset, + .qdev.size = sizeof(GPTimerUnit), + .qdev.props = (Property[]) { + DEFINE_PROP_UINT32("frequency", GPTimerUnit, freq_hz, 40000000), + DEFINE_PROP_UINT32("irq-line", GPTimerUnit, irq_line, 8), + DEFINE_PROP_UINT32("nr-timers", GPTimerUnit, nr_timers, 2), + DEFINE_PROP_END_OF_LIST() + } +}; + +static void grlib_gptimer_register(void) +{ + sysbus_register_withprop(&grlib_gptimer_info); +} + +device_init(grlib_gptimer_register) diff --git a/trace-events b/trace-events index e8fed0f..c56917a 100644 --- a/trace-events +++ b/trace-events @@ -213,3 +213,13 @@ disable qed_aio_write_data(void *s, void *acb, int ret, uint64_t offset, size_t disable qed_aio_write_prefill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64"" disable qed_aio_write_postfill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64"" disable qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu" + +# hw/grlib_gptimer.c +disable grlib_gptimer_enable(int id, uint32_t count) "timer:%d set count 0x%x and run" +disable grlib_gptimer_disabled(int id, uint32_t config) "timer:%d Timer disable config 0x%x" +disable grlib_gptimer_restart(int id, uint32_t reload) "timer:%d reload val: 0x%x" +disable grlib_gptimer_set_scaler(uint32_t scaler, uint32_t freq) "scaler:0x%x freq: 0x%x" +disable grlib_gptimer_hit(int id) "timer:%d HIT" +disable grlib_gptimer_readl(int id, const char *s, uint32_t val) "timer:%d %s 0x%x" +disable grlib_gptimer_writel(int id, const char *s, uint32_t val) "timer:%d %s 0x%x" +disable grlib_gptimer_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64"" -- 1.7.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH v3 2/5] SPARC: Emulation of GRLIB IRQMP 2011-01-21 17:00 ` [Qemu-devel] [PATCH v3 1/5] SPARC: Emulation of GRLIB GPTimer Fabien Chouteau @ 2011-01-21 17:00 ` Fabien Chouteau 2011-01-21 17:00 ` [Qemu-devel] [PATCH v3 3/5] SPARC: Emulation of GRLIB APB UART Fabien Chouteau 0 siblings, 1 reply; 10+ messages in thread From: Fabien Chouteau @ 2011-01-21 17:00 UTC (permalink / raw) To: qemu-devel; +Cc: Fabien Chouteau This device exposes two parameters: - set_pil_in (ptr) : A function to set the pil_in of the SPARC CPU - set_pil_in_opaque (ptr) : Opaque argument of the set_pil_in function Emulation of GrLib devices is base on the GRLIB IP Core User's Manual: http://www.gaisler.com/products/grlib/grip.pdf Signed-off-by: Fabien Chouteau <chouteau@adacore.com> --- hw/grlib.h | 38 ++++++ hw/grlib_irqmp.c | 380 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ trace-events | 6 + 3 files changed, 424 insertions(+), 0 deletions(-) diff --git a/hw/grlib.h b/hw/grlib.h index 776acf9..f92d6d3 100644 --- a/hw/grlib.h +++ b/hw/grlib.h @@ -32,6 +32,44 @@ * http://www.gaisler.com/products/grlib/grip.pdf */ +/* IRQMP */ + +typedef void (*set_pil_in_fn) (void *opaque, uint32_t pil_in); + +void grlib_irqmp_set_irq(void *opaque, int irq, int level); + +void grlib_irqmp_ack(DeviceState *dev, int intno); + +static inline +DeviceState *grlib_irqmp_create(target_phys_addr_t base, + CPUState *env, + qemu_irq **cpu_irqs, + uint32_t nr_irqs, + set_pil_in_fn set_pil_in) +{ + DeviceState *dev; + + assert(cpu_irqs != NULL); + + dev = qdev_create(NULL, "grlib,irqmp"); + qdev_prop_set_ptr(dev, "set_pil_in", set_pil_in); + qdev_prop_set_ptr(dev, "set_pil_in_opaque", env); + + if (qdev_init(dev)) { + return NULL; + } + + env->irq_manager = dev; + + sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); + + *cpu_irqs = qemu_allocate_irqs(grlib_irqmp_set_irq, + dev, + nr_irqs); + + return dev; +} + /* GPTimer */ static inline diff --git a/hw/grlib_irqmp.c b/hw/grlib_irqmp.c new file mode 100644 index 0000000..3db35ec --- /dev/null +++ b/hw/grlib_irqmp.c @@ -0,0 +1,380 @@ +/* + * QEMU GRLIB IRQMP Emulator + * + * (Multiprocessor and extended interrupt not supported) + * + * Copyright (c) 2010-2011 AdaCore + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "sysbus.h" +#include "cpu.h" + +#include "grlib.h" + +#include "trace.h" + +#define IRQMP_MAX_CPU 16 +#define IRQMP_REG_SIZE 256 /* Size of memory mapped registers */ + +/* Memory mapped register offsets */ +#define LEVEL_OFFSET 0x00 +#define PENDING_OFFSET 0x04 +#define FORCE0_OFFSET 0x08 +#define CLEAR_OFFSET 0x0C +#define MP_STATUS_OFFSET 0x10 +#define BROADCAST_OFFSET 0x14 +#define MASK_OFFSET 0x40 +#define FORCE_OFFSET 0x80 +#define EXTENDED_OFFSET 0xC0 + +typedef struct IRQMPState IRQMPState; + +typedef struct IRQMP +{ + SysBusDevice busdev; + + void *set_pil_in; + void *set_pil_in_opaque; + + IRQMPState *state; +} IRQMP; + +struct IRQMPState +{ + uint32_t level; + uint32_t pending; + uint32_t clear; + uint32_t broadcast; + + uint32_t mask[IRQMP_MAX_CPU]; + uint32_t force[IRQMP_MAX_CPU]; + uint32_t extended[IRQMP_MAX_CPU]; + + IRQMP *parent; +}; + +static void grlib_irqmp_check_irqs(IRQMPState *state) +{ + uint32_t pend = 0; + uint32_t level0 = 0; + uint32_t level1 = 0; + set_pil_in_fn set_pil_in; + + assert(state != NULL); + assert(state->parent != NULL); + + /* IRQ for CPU 0 (no SMP support) */ + pend = (state->pending | state->force[0]) + & state->mask[0]; + + level0 = pend & ~state->level; + level1 = pend & state->level; + + trace_grlib_irqmp_check_irqs(state->pending, state->force[0], + state->mask[0], level1, level0); + + set_pil_in = (set_pil_in_fn)state->parent->set_pil_in; + + /* Trigger level1 interrupt first and level0 if there is no level1 */ + if (level1 != 0) { + set_pil_in(state->parent->set_pil_in_opaque, level1); + } else { + set_pil_in(state->parent->set_pil_in_opaque, level0); + } +} + +void grlib_irqmp_ack(DeviceState *dev, int intno) +{ + SysBusDevice *sdev; + IRQMP *irqmp; + IRQMPState *state; + uint32_t mask; + + assert(dev != NULL); + + sdev = sysbus_from_qdev(dev); + assert(sdev != NULL); + + irqmp = FROM_SYSBUS(typeof (*irqmp), sdev); + assert(irqmp != NULL); + + state = irqmp->state; + assert(state != NULL); + + intno &= 15; + mask = 1 << intno; + + trace_grlib_irqmp_ack(intno); + + /* Clear registers */ + state->pending &= ~mask; + state->force[0] &= ~mask; /* Only CPU 0 (No SMP support) */ + + grlib_irqmp_check_irqs(state); +} + +void grlib_irqmp_set_irq(void *opaque, int irq, int level) +{ + IRQMP *irqmp; + IRQMPState *s; + int i = 0; + + assert(opaque != NULL); + + irqmp = FROM_SYSBUS(typeof (*irqmp), sysbus_from_qdev(opaque)); + assert(irqmp != NULL); + + s = irqmp->state; + assert(s != NULL); + assert(s->parent != NULL); + + + if (level) { + trace_grlib_irqmp_set_irq(irq); + + if (s->broadcast & 1 << irq) { + /* Broadcasted IRQ */ + for (i = 0; i < IRQMP_MAX_CPU; i++) { + s->force[i] |= 1 << irq; + } + } else { + s->pending |= 1 << irq; + } + grlib_irqmp_check_irqs(s); + + } +} + +static uint32_t grlib_irqmp_readl(void *opaque, target_phys_addr_t addr) +{ + IRQMP *irqmp = opaque; + IRQMPState *state; + + assert(irqmp != NULL); + state = irqmp->state; + assert(state != NULL); + + addr &= 0xff; + + /* global registers */ + switch (addr) + { + case LEVEL_OFFSET: + return state->level; + + case PENDING_OFFSET: + return state->pending; + + case FORCE0_OFFSET: + /* This register is an "alias" for the force register of CPU 0 */ + return state->force[0]; + + case CLEAR_OFFSET: + case MP_STATUS_OFFSET: + /* Always read as 0 */ + return 0; + + case BROADCAST_OFFSET: + return state->broadcast; + + default: + break; + } + + /* mask registers */ + if (addr >= MASK_OFFSET && addr < FORCE_OFFSET) { + int cpu = (addr - MASK_OFFSET) / 4; + assert(cpu >= 0 && cpu < IRQMP_MAX_CPU); + + return state->mask[cpu]; + } + + /* force registers */ + if (addr >= FORCE_OFFSET && addr < EXTENDED_OFFSET) { + int cpu = (addr - FORCE_OFFSET) / 4; + assert(cpu >= 0 && cpu < IRQMP_MAX_CPU); + + return state->force[cpu]; + } + + /* extended (not supported) */ + if (addr >= EXTENDED_OFFSET && addr < IRQMP_REG_SIZE) { + int cpu = (addr - EXTENDED_OFFSET) / 4; + assert(cpu >= 0 && cpu < IRQMP_MAX_CPU); + + return state->extended[cpu]; + } + + trace_grlib_irqmp_unknown_register("read", addr); + return 0; +} + +static void +grlib_irqmp_writel(void *opaque, target_phys_addr_t addr, uint32_t value) +{ + IRQMP *irqmp = opaque; + IRQMPState *state; + + assert(irqmp != NULL); + state = irqmp->state; + assert(state != NULL); + + addr &= 0xff; + + /* global registers */ + switch (addr) + { + case LEVEL_OFFSET: + value &= 0xFFFF << 1; /* clean up the value */ + state->level = value; + return; + + case PENDING_OFFSET: + /* Read Only */ + return; + + case FORCE0_OFFSET: + /* This register is an "alias" for the force register of CPU 0 */ + + value &= 0xFFFE; /* clean up the value */ + state->force[0] = value; + grlib_irqmp_check_irqs(irqmp->state); + return; + + case CLEAR_OFFSET: + value &= ~1; /* clean up the value */ + state->pending &= ~value; + return; + + case MP_STATUS_OFFSET: + /* Read Only (no SMP support) */ + return; + + case BROADCAST_OFFSET: + value &= 0xFFFE; /* clean up the value */ + state->broadcast = value; + return; + + default: + break; + } + + /* mask registers */ + if (addr >= MASK_OFFSET && addr < FORCE_OFFSET) { + int cpu = (addr - MASK_OFFSET) / 4; + assert(cpu >= 0 && cpu < IRQMP_MAX_CPU); + + value &= ~1; /* clean up the value */ + state->mask[cpu] = value; + grlib_irqmp_check_irqs(irqmp->state); + return; + } + + /* force registers */ + if (addr >= FORCE_OFFSET && addr < EXTENDED_OFFSET) { + int cpu = (addr - FORCE_OFFSET) / 4; + assert(cpu >= 0 && cpu < IRQMP_MAX_CPU); + + uint32_t force = value & 0xFFFE; + uint32_t clear = (value >> 16) & 0xFFFE; + uint32_t old = state->force[cpu]; + + state->force[cpu] = (old | force) & ~clear; + grlib_irqmp_check_irqs(irqmp->state); + return; + } + + /* extended (not supported) */ + if (addr >= EXTENDED_OFFSET && addr < IRQMP_REG_SIZE) { + int cpu = (addr - EXTENDED_OFFSET) / 4; + assert(cpu >= 0 && cpu < IRQMP_MAX_CPU); + + value &= 0xF; /* clean up the value */ + state->extended[cpu] = value; + return; + } + + trace_grlib_irqmp_unknown_register("write", addr); +} + +static CPUReadMemoryFunc * const grlib_irqmp_read[] = { + NULL, NULL, &grlib_irqmp_readl, +}; + +static CPUWriteMemoryFunc * const grlib_irqmp_write[] = { + NULL, NULL, &grlib_irqmp_writel, +}; + +static void grlib_irqmp_reset(DeviceState *d) +{ + IRQMP *irqmp = container_of(d, IRQMP, busdev.qdev); + assert(irqmp != NULL); + assert(irqmp->state != NULL); + + memset(irqmp->state, 0, sizeof *irqmp->state); + irqmp->state->parent = irqmp; +} + +static int grlib_irqmp_init(SysBusDevice *dev) +{ + IRQMP *irqmp = FROM_SYSBUS(typeof (*irqmp), dev); + int irqmp_regs; + + assert(irqmp != NULL); + + /* Check parameters */ + if (irqmp->set_pil_in == NULL) { + return -1; + } + + irqmp_regs = cpu_register_io_memory(grlib_irqmp_read, + grlib_irqmp_write, + irqmp, DEVICE_NATIVE_ENDIAN); + + irqmp->state = qemu_mallocz(sizeof *irqmp->state); + + if (irqmp_regs < 0) { + return -1; + } + + sysbus_init_mmio(dev, IRQMP_REG_SIZE, irqmp_regs); + + return 0; +} + +static SysBusDeviceInfo grlib_irqmp_info = { + .init = grlib_irqmp_init, + .qdev.name = "grlib,irqmp", + .qdev.reset = grlib_irqmp_reset, + .qdev.size = sizeof(IRQMP), + .qdev.props = (Property[]) { + DEFINE_PROP_PTR("set_pil_in", IRQMP, set_pil_in), + DEFINE_PROP_PTR("set_pil_in_opaque", IRQMP, set_pil_in_opaque), + DEFINE_PROP_END_OF_LIST(), + } +}; + +static void grlib_irqmp_register(void) +{ + sysbus_register_withprop(&grlib_irqmp_info); +} + +device_init(grlib_irqmp_register) diff --git a/trace-events b/trace-events index c56917a..8cb1e61 100644 --- a/trace-events +++ b/trace-events @@ -223,3 +223,9 @@ disable grlib_gptimer_hit(int id) "timer:%d HIT" disable grlib_gptimer_readl(int id, const char *s, uint32_t val) "timer:%d %s 0x%x" disable grlib_gptimer_writel(int id, const char *s, uint32_t val) "timer:%d %s 0x%x" disable grlib_gptimer_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64"" + +# hw/grlib_irqmp.c +disable grlib_irqmp_check_irqs(uint32_t pend, uint32_t force, uint32_t mask, uint32_t lvl1, uint32_t lvl2) "pend:0x%04x force:0x%04x mask:0x%04x lvl1:0x%04x lvl0:0x%04x\n" +disable grlib_irqmp_ack(int intno) "interrupt:%d" +disable grlib_irqmp_set_irq(int irq) "Raise CPU IRQ %d" +disable grlib_irqmp_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64"" -- 1.7.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH v3 3/5] SPARC: Emulation of GRLIB APB UART 2011-01-21 17:00 ` [Qemu-devel] [PATCH v3 2/5] SPARC: Emulation of GRLIB IRQMP Fabien Chouteau @ 2011-01-21 17:00 ` Fabien Chouteau 2011-01-21 17:00 ` [Qemu-devel] [PATCH v3 4/5] SPARC: Emulation of Leon3 Fabien Chouteau 0 siblings, 1 reply; 10+ messages in thread From: Fabien Chouteau @ 2011-01-21 17:00 UTC (permalink / raw) To: qemu-devel; +Cc: Fabien Chouteau This device exposes one parameter: - chardev (ptr) : Pointer to a qemu character device Emulation of GrLib devices is base on the GRLIB IP Core User's Manual: http://www.gaisler.com/products/grlib/grip.pdf Signed-off-by: Fabien Chouteau <chouteau@adacore.com> --- hw/grlib.h | 23 ++++++ hw/grlib_apbuart.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++++++++ trace-events | 4 + 3 files changed, 216 insertions(+), 0 deletions(-) diff --git a/hw/grlib.h b/hw/grlib.h index f92d6d3..fdf4b11 100644 --- a/hw/grlib.h +++ b/hw/grlib.h @@ -100,4 +100,27 @@ DeviceState *grlib_gptimer_create(target_phys_addr_t base, return dev; } +/* APB UART */ + +static inline +DeviceState *grlib_apbuart_create(target_phys_addr_t base, + CharDriverState *serial, + qemu_irq irq) +{ + DeviceState *dev; + + dev = qdev_create(NULL, "grlib,apbuart"); + qdev_prop_set_chr(dev, "chrdev", serial); + + if (qdev_init(dev)) { + return NULL; + } + + sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); + + sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq); + + return dev; +} + #endif /* ! _GRLIB_H_ */ diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c new file mode 100644 index 0000000..e603419 --- /dev/null +++ b/hw/grlib_apbuart.c @@ -0,0 +1,189 @@ +/* + * QEMU GRLIB APB UART Emulator + * + * Copyright (c) 2010-2011 AdaCore + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "sysbus.h" +#include "qemu-char.h" + +#include "trace.h" + +#define UART_REG_SIZE 20 /* Size of memory mapped registers */ + +/* UART status register fields */ +#define UART_DATA_READY (1 << 0) +#define UART_TRANSMIT_SHIFT_EMPTY (1 << 1) +#define UART_TRANSMIT_FIFO_EMPTY (1 << 2) +#define UART_BREAK_RECEIVED (1 << 3) +#define UART_OVERRUN (1 << 4) +#define UART_PARITY_ERROR (1 << 5) +#define UART_FRAMING_ERROR (1 << 6) +#define UART_TRANSMIT_FIFO_HALF (1 << 7) +#define UART_RECEIVE_FIFO_HALF (1 << 8) +#define UART_TRANSMIT_FIFO_FULL (1 << 9) +#define UART_RECEIVE_FIFO_FULL (1 << 10) + +/* UART control register fields */ +#define UART_RECEIVE_ENABLE (1 << 0) +#define UART_TRANSMIT_ENABLE (1 << 1) +#define UART_RECEIVE_INTERRUPT (1 << 2) +#define UART_TRANSMIT_INTERRUPT (1 << 3) +#define UART_PARITY_SELECT (1 << 4) +#define UART_PARITY_ENABLE (1 << 5) +#define UART_FLOW_CONTROL (1 << 6) +#define UART_LOOPBACK (1 << 7) +#define UART_EXTERNAL_CLOCK (1 << 8) +#define UART_RECEIVE_FIFO_INTERRUPT (1 << 9) +#define UART_TRANSMIT_FIFO_INTERRUPT (1 << 10) +#define UART_FIFO_DEBUG_MODE (1 << 11) +#define UART_OUTPUT_ENABLE (1 << 12) +#define UART_FIFO_AVAILABLE (1 << 31) + +/* Memory mapped register offsets */ +#define DATA_OFFSET 0x00 +#define STATUS_OFFSET 0x04 +#define CONTROL_OFFSET 0x08 +#define SCALER_OFFSET 0x0C /* not supported */ +#define FIFO_DEBUG_OFFSET 0x10 /* not supported */ + +typedef struct UART +{ + SysBusDevice busdev; + + qemu_irq irq; + + CharDriverState *chr; + + /* registers */ + uint32_t receive; + uint32_t status; + uint32_t control; +} UART; + +static int grlib_apbuart_can_receive(void *opaque) +{ + UART *uart = opaque; + + return !!(uart->status & UART_DATA_READY); +} + +static void grlib_apbuart_receive(void *opaque, const uint8_t *buf, int size) +{ + UART *uart = opaque; + + uart->receive = *buf; + uart->status |= UART_DATA_READY; + + if (uart->control & UART_RECEIVE_INTERRUPT) { + qemu_irq_pulse(uart->irq); + } +} + +static void grlib_apbuart_event(void *opaque, int event) +{ + trace_grlib_apbuart_event(event); +} + +static void +grlib_apbuart_writel(void *opaque, target_phys_addr_t addr, uint32_t value) +{ + UART *uart = opaque; + unsigned char c = 0; + + addr &= 0xff; + + /* Unit registers */ + switch (addr) + { + case DATA_OFFSET: + c = value & 0xFF; + qemu_chr_write(uart->chr, &c, 1); + return; + + case STATUS_OFFSET: + /* Read Only */ + return; + + case CONTROL_OFFSET: + /* Not supported */ + return; + + case SCALER_OFFSET: + /* Not supported */ + return; + + default: + break; + } + + trace_grlib_apbuart_unknown_register("write", addr); +} + +static CPUReadMemoryFunc * const grlib_apbuart_read[] = { + NULL, NULL, NULL, +}; + +static CPUWriteMemoryFunc * const grlib_apbuart_write[] = { + NULL, NULL, grlib_apbuart_writel, +}; + +static int grlib_apbuart_init(SysBusDevice *dev) +{ + UART *uart = FROM_SYSBUS(typeof (*uart), dev); + int uart_regs = 0; + + qemu_chr_add_handlers(uart->chr, + grlib_apbuart_can_receive, + grlib_apbuart_receive, + grlib_apbuart_event, + uart); + + sysbus_init_irq(dev, &uart->irq); + + uart_regs = cpu_register_io_memory(grlib_apbuart_read, + grlib_apbuart_write, + uart, DEVICE_NATIVE_ENDIAN); + if (uart_regs < 0) { + return -1; + } + + sysbus_init_mmio(dev, UART_REG_SIZE, uart_regs); + + return 0; +} + +static SysBusDeviceInfo grlib_gptimer_info = { + .init = grlib_apbuart_init, + .qdev.name = "grlib,apbuart", + .qdev.size = sizeof(UART), + .qdev.props = (Property[]) { + DEFINE_PROP_CHR("chrdev", UART, chr), + DEFINE_PROP_END_OF_LIST() + } +}; + +static void grlib_gptimer_register(void) +{ + sysbus_register_withprop(&grlib_gptimer_info); +} + +device_init(grlib_gptimer_register) diff --git a/trace-events b/trace-events index 8cb1e61..2390cbb 100644 --- a/trace-events +++ b/trace-events @@ -229,3 +229,7 @@ disable grlib_irqmp_check_irqs(uint32_t pend, uint32_t force, uint32_t mask, uin disable grlib_irqmp_ack(int intno) "interrupt:%d" disable grlib_irqmp_set_irq(int irq) "Raise CPU IRQ %d" disable grlib_irqmp_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64"" + +# hw/grlib_apbuart.c +disable grlib_apbuart_event(int event) "event:%d" +disable grlib_apbuart_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64"" -- 1.7.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH v3 4/5] SPARC: Emulation of Leon3 2011-01-21 17:00 ` [Qemu-devel] [PATCH v3 3/5] SPARC: Emulation of GRLIB APB UART Fabien Chouteau @ 2011-01-21 17:00 ` Fabien Chouteau 2011-01-21 17:00 ` [Qemu-devel] [PATCH v3 5/5] SPARC: Add asr17 register support Fabien Chouteau 2011-01-21 19:02 ` [Qemu-devel] [PATCH v3 4/5] SPARC: Emulation of Leon3 Blue Swirl 0 siblings, 2 replies; 10+ messages in thread From: Fabien Chouteau @ 2011-01-21 17:00 UTC (permalink / raw) To: qemu-devel; +Cc: Fabien Chouteau Leon3 is an open-source VHDL System-On-Chip, well known in space industry (more information on http://www.gaisler.com). Leon3 is made of multiple components available in the GrLib VHDL library. Three devices are implemented: uart, timers and IRQ manager. You can find code for these peripherals in the grlib_* files. Signed-off-by: Fabien Chouteau <chouteau@adacore.com> --- Makefile.target | 5 +- hw/leon3.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++ target-sparc/cpu.h | 37 +++++--- target-sparc/helper.c | 7 +- target-sparc/helper.h | 1 + target-sparc/op_helper.c | 154 ++++++++++++++++++++++++++++++- target-sparc/translate.c | 13 ++- 7 files changed, 426 insertions(+), 22 deletions(-) diff --git a/Makefile.target b/Makefile.target index e15b1c4..efd8406 100644 --- a/Makefile.target +++ b/Makefile.target @@ -286,7 +286,10 @@ obj-sparc-y += cirrus_vga.o else obj-sparc-y = sun4m.o lance.o tcx.o sun4m_iommu.o slavio_intctl.o obj-sparc-y += slavio_timer.o slavio_misc.o sparc32_dma.o -obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o +obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o leon3.o + +# GRLIB +obj-sparc-y += grlib_gptimer.o grlib_irqmp.o grlib_apbuart.o endif obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o diff --git a/hw/leon3.c b/hw/leon3.c new file mode 100644 index 0000000..f8f994a --- /dev/null +++ b/hw/leon3.c @@ -0,0 +1,231 @@ +/* + * QEMU Leon3 System Emulator + * + * Copyright (c) 2010-2011 AdaCore + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "hw.h" +#include "qemu-timer.h" +#include "qemu-char.h" +#include "sysemu.h" +#include "boards.h" +#include "loader.h" +#include "elf.h" + +#include "grlib.h" + +//#define DEBUG_LEON3 + +#ifdef DEBUG_LEON3 +#define DPRINTF(fmt, ...) \ + do { printf("Leon3: " fmt , ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) +#endif + +/* Default system clock. */ +#define CPU_CLK (40 * 1000 * 1000) + +#define PROM_FILENAME "u-boot.bin" + +#define MAX_PILS 16 + +typedef struct ResetData { + CPUState *env; + uint32_t entry; /* save kernel entry in case of reset */ +} ResetData; + +static void main_cpu_reset(void *opaque) +{ + ResetData *s = (ResetData *)opaque; + CPUState *env = s->env; + + cpu_reset(env); + + env->halted = 0; + env->pc = s->entry; + env->npc = s->entry + 4; +} + +static void leon3_irq_ack(void *irq_manager, int intno) +{ + grlib_irqmp_ack((DeviceState *)irq_manager, intno); + leon3_cache_control_int(); +} + +static void leon3_set_pil_in(void *opaque, uint32_t pil_in) +{ + CPUState *env = (CPUState *)opaque; + + assert(env != NULL); + + env->pil_in = pil_in; + + if (env->pil_in && (env->interrupt_index == 0 || + (env->interrupt_index & ~15) == TT_EXTINT)) { + unsigned int i; + + for (i = 15; i > 0; i--) { + if (env->pil_in & (1 << i)) { + int old_interrupt = env->interrupt_index; + + env->interrupt_index = TT_EXTINT | i; + if (old_interrupt != env->interrupt_index) { + DPRINTF("Set CPU IRQ %d\n", i); + cpu_interrupt(env, CPU_INTERRUPT_HARD); + } + break; + } + } + } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) { + DPRINTF("Reset CPU IRQ %d\n", env->interrupt_index & 15); + env->interrupt_index = 0; + cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); + } +} + +static void leon3_generic_hw_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, + const char *cpu_model) +{ + CPUState *env; + ram_addr_t ram_offset, prom_offset; + int ret; + char *filename; + qemu_irq *cpu_irqs = NULL; + int bios_size; + int prom_size; + int aligned_bios_size; + ResetData *reset_info; + + /* Init CPU */ + if (!cpu_model) { + cpu_model = "LEON3"; + } + + env = cpu_init(cpu_model); + if (!env) { + fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n"); + exit(1); + } + + cpu_sparc_set_id(env, 0); + + /* Reset data */ + reset_info = qemu_mallocz(sizeof(ResetData)); + reset_info->env = env; + qemu_register_reset(main_cpu_reset, reset_info); + + /* Allocate IRQ manager */ + grlib_irqmp_create(0x80000200, env, &cpu_irqs, MAX_PILS, &leon3_set_pil_in); + + env->qemu_irq_ack = leon3_irq_ack; + + /* Allocate RAM */ + if ((uint64_t)ram_size > (1UL << 30)) { + fprintf(stderr, + "qemu: Too much memory for this machine: %d, maximum 1G\n", + (unsigned int)(ram_size / (1024 * 1024))); + exit(1); + } + + ram_offset = qemu_ram_alloc(NULL, "leon3.ram", ram_size); + cpu_register_physical_memory(0x40000000, ram_size, ram_offset | IO_MEM_RAM); + + /* Allocate BIOS */ + prom_size = 8 * 1024 * 1024; /* 8Mb */ + prom_offset = qemu_ram_alloc(NULL, "Leon3.bios", prom_size); + cpu_register_physical_memory(0x00000000, prom_size, + prom_offset | IO_MEM_ROM); + + /* Load boot prom */ + if (bios_name == NULL) { + bios_name = PROM_FILENAME; + } + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + + bios_size = get_image_size(filename); + + if (bios_size > prom_size) { + fprintf(stderr, "qemu: could not load prom '%s': file too big \n", + filename); + exit(1); + } + + if (bios_size > 0) { + aligned_bios_size = + (bios_size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK; + + ret = load_image_targphys(filename, 0x00000000, bios_size); + if (ret < 0 || ret > prom_size) { + fprintf(stderr, "qemu: could not load prom '%s'\n", filename); + exit(1); + } + } + else if (kernel_filename == NULL) { + fprintf(stderr,"Can't read bios image %s\n", filename); + exit(1); + } + + /* Can directly load an application. */ + if (kernel_filename != NULL) { + long kernel_size; + uint64_t entry; + + kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL, + 1 /* big endian */, ELF_MACHINE, 0); + if (kernel_size < 0) { + fprintf(stderr, "qemu: could not load kernel '%s'\n", + kernel_filename); + exit(1); + } + if (bios_size <= 0) { + /* If there is no bios/monitor, start the application. */ + env->pc = entry; + env->npc = entry + 4; + reset_info->entry = entry; + } + } + + /* Allocate timers */ + grlib_gptimer_create(0x80000300, 2, CPU_CLK, cpu_irqs, 6); + + /* Allocate uart */ + if (serial_hds[0]) { + grlib_apbuart_create(0x80000100, serial_hds[0], cpu_irqs[3]); + } +} + +QEMUMachine leon3_generic_machine = { + .name = "leon3_generic", + .desc = "Leon-3 generic", + .init = leon3_generic_hw_init, + .use_scsi = 0, +}; + +static void leon3_machine_init(void) +{ + qemu_register_machine(&leon3_generic_machine); +} + +machine_init(leon3_machine_init); diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 7225b2e..5c50d9e 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -252,20 +252,21 @@ typedef struct sparc_def_t { uint32_t maxtl; } sparc_def_t; -#define CPU_FEATURE_FLOAT (1 << 0) -#define CPU_FEATURE_FLOAT128 (1 << 1) -#define CPU_FEATURE_SWAP (1 << 2) -#define CPU_FEATURE_MUL (1 << 3) -#define CPU_FEATURE_DIV (1 << 4) -#define CPU_FEATURE_FLUSH (1 << 5) -#define CPU_FEATURE_FSQRT (1 << 6) -#define CPU_FEATURE_FMUL (1 << 7) -#define CPU_FEATURE_VIS1 (1 << 8) -#define CPU_FEATURE_VIS2 (1 << 9) -#define CPU_FEATURE_FSMULD (1 << 10) -#define CPU_FEATURE_HYPV (1 << 11) -#define CPU_FEATURE_CMT (1 << 12) -#define CPU_FEATURE_GL (1 << 13) +#define CPU_FEATURE_FLOAT (1 << 0) +#define CPU_FEATURE_FLOAT128 (1 << 1) +#define CPU_FEATURE_SWAP (1 << 2) +#define CPU_FEATURE_MUL (1 << 3) +#define CPU_FEATURE_DIV (1 << 4) +#define CPU_FEATURE_FLUSH (1 << 5) +#define CPU_FEATURE_FSQRT (1 << 6) +#define CPU_FEATURE_FMUL (1 << 7) +#define CPU_FEATURE_VIS1 (1 << 8) +#define CPU_FEATURE_VIS2 (1 << 9) +#define CPU_FEATURE_FSMULD (1 << 10) +#define CPU_FEATURE_HYPV (1 << 11) +#define CPU_FEATURE_CMT (1 << 12) +#define CPU_FEATURE_GL (1 << 13) +#define CPU_FEATURE_TA0_SHUTDOWN (1 << 14) /* Shutdown on "ta 0x0" */ #ifndef TARGET_SPARC64 #define CPU_DEFAULT_FEATURES (CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | \ CPU_FEATURE_MUL | CPU_FEATURE_DIV | \ @@ -437,6 +438,12 @@ typedef struct CPUSPARCState { #define SOFTINT_REG_MASK (SOFTINT_STIMER|SOFTINT_INTRMASK|SOFTINT_TIMER) #endif sparc_def_t *def; + + void *irq_manager; + void (*qemu_irq_ack) (void *irq_manager, int intno); + + /* Leon3 cache control */ + uint32_t cache_control; } CPUSPARCState; #ifndef NO_CPU_IO_DEFS @@ -469,6 +476,8 @@ int cpu_cwp_inc(CPUState *env1, int cwp); int cpu_cwp_dec(CPUState *env1, int cwp); void cpu_set_cwp(CPUState *env1, int new_cwp); +void leon3_cache_control_int(void); + /* sun4m.c, sun4u.c */ void cpu_check_irqs(CPUSPARCState *env); diff --git a/target-sparc/helper.c b/target-sparc/helper.c index 6b337ca..ec6ac27 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -770,6 +770,7 @@ void cpu_reset(CPUSPARCState *env) env->pc = 0; env->npc = env->pc + 4; #endif + env->cache_control = 0; } static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model) @@ -1274,20 +1275,20 @@ static const sparc_def_t sparc_defs[] = { .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, .nwindows = 8, - .features = CPU_DEFAULT_FEATURES, + .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN, }, { .name = "LEON3", .iu_version = 0xf3000000, .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */ .mmu_version = 0xf3000000, - .mmu_bm = 0x00004000, + .mmu_bm = 0x00000000, .mmu_ctpr_mask = 0x007ffff0, .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, .nwindows = 8, - .features = CPU_DEFAULT_FEATURES, + .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN, }, #endif }; diff --git a/target-sparc/helper.h b/target-sparc/helper.h index e6d82f9..12e8557 100644 --- a/target-sparc/helper.h +++ b/target-sparc/helper.h @@ -85,6 +85,7 @@ DEF_HELPER_0(fcmpeq_fcc2, void) DEF_HELPER_0(fcmpeq_fcc3, void) #endif DEF_HELPER_1(raise_exception, void, int) +DEF_HELPER_0(shutdown, void) #define F_HELPER_0_0(name) DEF_HELPER_0(f ## name, void) #define F_HELPER_DQ_0_0(name) \ F_HELPER_0_0(name ## d); \ diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index b70970a..66b7cdf 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -1,6 +1,7 @@ #include "exec.h" #include "host-utils.h" #include "helper.h" +#include "sysemu.h" //#define DEBUG_MMU //#define DEBUG_MXCC @@ -9,6 +10,7 @@ //#define DEBUG_ASI //#define DEBUG_PCALL //#define DEBUG_PSTATE +//#define DEBUG_CACHE_CONTROL #ifdef DEBUG_MMU #define DPRINTF_MMU(fmt, ...) \ @@ -36,6 +38,13 @@ #define DPRINTF_PSTATE(fmt, ...) do {} while (0) #endif +#ifdef DEBUG_CACHE_CONTROL +#define DPRINTF_CACHE_CONTROL(fmt, ...) \ + do { printf("CACHE_CONTROL: " fmt , ## __VA_ARGS__); } while (0) +#else +#define DPRINTF_CACHE_CONTROL(fmt, ...) do {} while (0) +#endif + #ifdef TARGET_SPARC64 #ifndef TARGET_ABI32 #define AM_CHECK(env1) ((env1)->pstate & PS_AM) @@ -49,6 +58,27 @@ #define QT0 (env->qt0) #define QT1 (env->qt1) +/* Leon3 cache control */ + +/* Cache control: emulate the behavior of cache control registers but without + any effect on the emulated */ + +#define CACHE_STATE_MASK 0x3 +#define CACHE_DISABLED 0x0 +#define CACHE_FROZEN 0x1 +#define CACHE_ENABLED 0x3 + +/* Cache Control register fields */ + +#define CACHE_CTRL_IF (1 << 4) /* Instruction Cache Freeze on Interrupt */ +#define CACHE_CTRL_DF (1 << 5) /* Data Cache Freeze on Interrupt */ +#define CACHE_CTRL_DP (1 << 14) /* Data cache flush pending */ +#define CACHE_CTRL_IP (1 << 15) /* Instruction cache flush pending */ +#define CACHE_CTRL_IB (1 << 16) /* Instruction burst fetch */ +#define CACHE_CTRL_FI (1 << 21) /* Flush Instruction cache (Write only) */ +#define CACHE_CTRL_FD (1 << 22) /* Flush Data cache (Write only) */ +#define CACHE_CTRL_DS (1 << 23) /* Data cache snoop enable */ + #if defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64) static void do_unassigned_access(target_ulong addr, int is_write, int is_exec, int is_asi, int size); @@ -294,6 +324,11 @@ void HELPER(raise_exception)(int tt) raise_exception(tt); } +void helper_shutdown(void) +{ + qemu_system_shutdown_request(); +} + void helper_check_align(target_ulong addr, uint32_t align) { if (addr & align) { @@ -1612,6 +1647,103 @@ static void dump_asi(const char *txt, target_ulong addr, int asi, int size, #ifndef TARGET_SPARC64 #ifndef CONFIG_USER_ONLY + + +/* Leon3 cache control */ + +void leon3_cache_control_int(void) +{ + uint32_t state = 0; + + if (env->cache_control & CACHE_CTRL_IF) { + /* Instruction cache state */ + state = env->cache_control & CACHE_STATE_MASK; + if (state == CACHE_ENABLED) { + state = CACHE_FROZEN; + DPRINTF_CACHE_CONTROL("Instruction cache: freeze\n"); + } + + env->cache_control &= ~CACHE_STATE_MASK; + env->cache_control |= state; + } + + if (env->cache_control & CACHE_CTRL_DF) { + /* Data cache state */ + state = (env->cache_control >> 2) & CACHE_STATE_MASK; + if (state == CACHE_ENABLED) { + state = CACHE_FROZEN; + DPRINTF_CACHE_CONTROL("Data cache: freeze\n"); + } + + env->cache_control &= ~(CACHE_STATE_MASK << 2); + env->cache_control |= (state << 2); + } +} + +static void leon3_cache_control_st(target_ulong addr, uint64_t val, int size) +{ + DPRINTF_CACHE_CONTROL("st addr:%08x, val:%" PRIx64 ", size:%d\n", + addr, val, size); + + if (size != 4) { + DPRINTF_CACHE_CONTROL("32bits only\n"); + return; + } + + switch (addr) { + case 0x00: /* Cache control */ + + /* These values must always be read as zeros */ + val &= ~CACHE_CTRL_FD; + val &= ~CACHE_CTRL_FI; + val &= ~CACHE_CTRL_IB; + val &= ~CACHE_CTRL_IP; + val &= ~CACHE_CTRL_DP; + + env->cache_control = val; + break; + case 0x04: /* Instruction cache configuration */ + case 0x08: /* Data cache configuration */ + /* Read Only */ + break; + default: + DPRINTF_CACHE_CONTROL("write unknown register %08x\n", addr); + break; + }; +} + +static uint64_t leon3_cache_control_ld(target_ulong addr, int size) +{ + uint64_t ret = 0; + + if (size != 4) { + DPRINTF_CACHE_CONTROL("32bits only\n"); + return 0; + } + + switch (addr) { + case 0x00: /* Cache control */ + ret = env->cache_control; + break; + + /* Configuration registers are read and only always keep those + predefined values */ + + case 0x04: /* Instruction cache configuration */ + ret = 0x10220000; + break; + case 0x08: /* Data cache configuration */ + ret = 0x18220000; + break; + default: + DPRINTF_CACHE_CONTROL("read unknown register %08x\n", addr); + break; + }; + DPRINTF_CACHE_CONTROL("st addr:%08x, ret:%" PRIx64 ", size:%d\n", + addr, ret, size); + return ret; +} + uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) { uint64_t ret = 0; @@ -1621,8 +1753,13 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) helper_check_align(addr, size - 1); switch (asi) { - case 2: /* SuperSparc MXCC registers */ + case 2: /* SuperSparc MXCC registers and Leon3 cache control */ switch (addr) { + case 0x00: /* Leon3 Cache Control */ + case 0x08: /* Leon3 Instruction Cache config */ + case 0x0C: /* Leon3 Date Cache config */ + ret = leon3_cache_control_ld(addr, size); + break; case 0x01c00a00: /* MXCC control register */ if (size == 8) ret = env->mxccregs[3]; @@ -1850,8 +1987,14 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size) { helper_check_align(addr, size - 1); switch(asi) { - case 2: /* SuperSparc MXCC registers */ + case 2: /* SuperSparc MXCC registers and Leon3 cache control */ switch (addr) { + case 0x00: /* Leon3 Cache Control */ + case 0x08: /* Leon3 Instruction Cache config */ + case 0x0C: /* Leon3 Date Cache config */ + leon3_cache_control_st(addr, val, size); + break; + case 0x01c00000: /* MXCC stream data register 0 */ if (size == 8) env->mxccdata[0] = val; @@ -4177,6 +4320,13 @@ void do_interrupt(CPUState *env) env->pc = env->tbr; env->npc = env->pc + 4; env->exception_index = -1; + +#if !defined(CONFIG_USER_ONLY) + /* IRQ acknowledgment */ + if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) { + env->qemu_irq_ack(env->irq_manager, intno); + } +#endif } #endif diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 21c5675..dff0f19 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -1997,8 +1997,9 @@ static void disas_sparc_insn(DisasContext * dc) } else tcg_gen_mov_tl(cpu_dst, cpu_src1); } + cond = GET_FIELD(insn, 3, 6); - if (cond == 0x8) { + if (cond == 0x8) { /* Trap Always */ save_state(dc, cpu_cond); if ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)) @@ -2007,7 +2008,15 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK); tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP); tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst); - gen_helper_raise_exception(cpu_tmp32); + + if (rs2 == 0 && + dc->def->features & CPU_FEATURE_TA0_SHUTDOWN) { + + gen_helper_shutdown(); + + } else { + gen_helper_raise_exception(cpu_tmp32); + } } else if (cond != 0) { TCGv r_cond = tcg_temp_new(); int l1; -- 1.7.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH v3 5/5] SPARC: Add asr17 register support 2011-01-21 17:00 ` [Qemu-devel] [PATCH v3 4/5] SPARC: Emulation of Leon3 Fabien Chouteau @ 2011-01-21 17:00 ` Fabien Chouteau 2011-01-21 19:02 ` [Qemu-devel] [PATCH v3 4/5] SPARC: Emulation of Leon3 Blue Swirl 1 sibling, 0 replies; 10+ messages in thread From: Fabien Chouteau @ 2011-01-21 17:00 UTC (permalink / raw) To: qemu-devel; +Cc: Fabien Chouteau This register is activated by CPU_FEATURE_ASR17 in the feature field. Signed-off-by: Fabien Chouteau <chouteau@adacore.com> --- target-sparc/cpu.h | 1 + target-sparc/helper.c | 3 ++- target-sparc/translate.c | 11 +++++++++++ 3 files changed, 14 insertions(+), 1 deletions(-) diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 5c50d9e..6f5990b 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -267,6 +267,7 @@ typedef struct sparc_def_t { #define CPU_FEATURE_CMT (1 << 12) #define CPU_FEATURE_GL (1 << 13) #define CPU_FEATURE_TA0_SHUTDOWN (1 << 14) /* Shutdown on "ta 0x0" */ +#define CPU_FEATURE_ASR17 (1 << 15) #ifndef TARGET_SPARC64 #define CPU_DEFAULT_FEATURES (CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | \ CPU_FEATURE_MUL | CPU_FEATURE_DIV | \ diff --git a/target-sparc/helper.c b/target-sparc/helper.c index ec6ac27..2f3d1e6 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -1288,7 +1288,8 @@ static const sparc_def_t sparc_defs[] = { .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, .nwindows = 8, - .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN, + .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN | + CPU_FEATURE_ASR17, }, #endif }; diff --git a/target-sparc/translate.c b/target-sparc/translate.c index dff0f19..e26462e 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2067,6 +2067,17 @@ static void disas_sparc_insn(DisasContext * dc) case 0x10 ... 0x1f: /* implementation-dependent in the SPARCv8 manual, rdy on the microSPARC II */ + /* Read Asr17 */ + if (rs1 == 0x11 && dc->def->features & CPU_FEATURE_ASR17) { + TCGv r_const; + + /* Read Asr17 for a Leon3 monoprocessor */ + r_const = tcg_const_tl((1 << 8) + | (dc->def->nwindows - 1)); + gen_movl_TN_reg(rd, r_const); + tcg_temp_free(r_const); + break; + } #endif gen_movl_TN_reg(rd, cpu_y); break; -- 1.7.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH v3 4/5] SPARC: Emulation of Leon3 2011-01-21 17:00 ` [Qemu-devel] [PATCH v3 4/5] SPARC: Emulation of Leon3 Fabien Chouteau 2011-01-21 17:00 ` [Qemu-devel] [PATCH v3 5/5] SPARC: Add asr17 register support Fabien Chouteau @ 2011-01-21 19:02 ` Blue Swirl 2011-01-21 19:09 ` Blue Swirl 1 sibling, 1 reply; 10+ messages in thread From: Blue Swirl @ 2011-01-21 19:02 UTC (permalink / raw) To: Fabien Chouteau; +Cc: qemu-devel On Fri, Jan 21, 2011 at 5:00 PM, Fabien Chouteau <chouteau@adacore.com> wrote: > Leon3 is an open-source VHDL System-On-Chip, well known in space industry (more > information on http://www.gaisler.com). > > Leon3 is made of multiple components available in the GrLib VHDL library. > Three devices are implemented: uart, timers and IRQ manager. > You can find code for these peripherals in the grlib_* files. > > Signed-off-by: Fabien Chouteau <chouteau@adacore.com> > --- > Makefile.target | 5 +- > hw/leon3.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++ > target-sparc/cpu.h | 37 +++++--- > target-sparc/helper.c | 7 +- > target-sparc/helper.h | 1 + > target-sparc/op_helper.c | 154 ++++++++++++++++++++++++++++++- > target-sparc/translate.c | 13 ++- > 7 files changed, 426 insertions(+), 22 deletions(-) > > diff --git a/Makefile.target b/Makefile.target > index e15b1c4..efd8406 100644 > --- a/Makefile.target > +++ b/Makefile.target > @@ -286,7 +286,10 @@ obj-sparc-y += cirrus_vga.o > else > obj-sparc-y = sun4m.o lance.o tcx.o sun4m_iommu.o slavio_intctl.o > obj-sparc-y += slavio_timer.o slavio_misc.o sparc32_dma.o > -obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o > +obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o leon3.o > + > +# GRLIB > +obj-sparc-y += grlib_gptimer.o grlib_irqmp.o grlib_apbuart.o > endif > > obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o > diff --git a/hw/leon3.c b/hw/leon3.c > new file mode 100644 > index 0000000..f8f994a > --- /dev/null > +++ b/hw/leon3.c > @@ -0,0 +1,231 @@ > +/* > + * QEMU Leon3 System Emulator > + * > + * Copyright (c) 2010-2011 AdaCore > + * > + * Permission is hereby granted, free of charge, to any person obtaining a copy > + * of this software and associated documentation files (the "Software"), to deal > + * in the Software without restriction, including without limitation the rights > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell > + * copies of the Software, and to permit persons to whom the Software is > + * furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice shall be included in > + * all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN > + * THE SOFTWARE. > + */ > +#include "hw.h" > +#include "qemu-timer.h" > +#include "qemu-char.h" > +#include "sysemu.h" > +#include "boards.h" > +#include "loader.h" > +#include "elf.h" > + > +#include "grlib.h" > + > +//#define DEBUG_LEON3 > + > +#ifdef DEBUG_LEON3 > +#define DPRINTF(fmt, ...) \ > + do { printf("Leon3: " fmt , ## __VA_ARGS__); } while (0) > +#else > +#define DPRINTF(fmt, ...) > +#endif > + > +/* Default system clock. */ > +#define CPU_CLK (40 * 1000 * 1000) > + > +#define PROM_FILENAME "u-boot.bin" > + > +#define MAX_PILS 16 > + > +typedef struct ResetData { > + CPUState *env; > + uint32_t entry; /* save kernel entry in case of reset */ > +} ResetData; > + > +static void main_cpu_reset(void *opaque) > +{ > + ResetData *s = (ResetData *)opaque; > + CPUState *env = s->env; > + > + cpu_reset(env); > + > + env->halted = 0; > + env->pc = s->entry; > + env->npc = s->entry + 4; > +} > + > +static void leon3_irq_ack(void *irq_manager, int intno) > +{ > + grlib_irqmp_ack((DeviceState *)irq_manager, intno); > + leon3_cache_control_int(); > +} > + > +static void leon3_set_pil_in(void *opaque, uint32_t pil_in) > +{ > + CPUState *env = (CPUState *)opaque; > + > + assert(env != NULL); > + > + env->pil_in = pil_in; > + > + if (env->pil_in && (env->interrupt_index == 0 || > + (env->interrupt_index & ~15) == TT_EXTINT)) { > + unsigned int i; > + > + for (i = 15; i > 0; i--) { > + if (env->pil_in & (1 << i)) { > + int old_interrupt = env->interrupt_index; > + > + env->interrupt_index = TT_EXTINT | i; > + if (old_interrupt != env->interrupt_index) { > + DPRINTF("Set CPU IRQ %d\n", i); > + cpu_interrupt(env, CPU_INTERRUPT_HARD); > + } > + break; > + } > + } > + } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) { > + DPRINTF("Reset CPU IRQ %d\n", env->interrupt_index & 15); > + env->interrupt_index = 0; > + cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); > + } > +} > + > +static void leon3_generic_hw_init(ram_addr_t ram_size, > + const char *boot_device, > + const char *kernel_filename, > + const char *kernel_cmdline, > + const char *initrd_filename, > + const char *cpu_model) > +{ > + CPUState *env; > + ram_addr_t ram_offset, prom_offset; > + int ret; > + char *filename; > + qemu_irq *cpu_irqs = NULL; > + int bios_size; > + int prom_size; > + int aligned_bios_size; > + ResetData *reset_info; > + > + /* Init CPU */ > + if (!cpu_model) { > + cpu_model = "LEON3"; > + } > + > + env = cpu_init(cpu_model); > + if (!env) { > + fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n"); > + exit(1); > + } > + > + cpu_sparc_set_id(env, 0); > + > + /* Reset data */ > + reset_info = qemu_mallocz(sizeof(ResetData)); > + reset_info->env = env; > + qemu_register_reset(main_cpu_reset, reset_info); > + > + /* Allocate IRQ manager */ > + grlib_irqmp_create(0x80000200, env, &cpu_irqs, MAX_PILS, &leon3_set_pil_in); > + > + env->qemu_irq_ack = leon3_irq_ack; > + > + /* Allocate RAM */ > + if ((uint64_t)ram_size > (1UL << 30)) { > + fprintf(stderr, > + "qemu: Too much memory for this machine: %d, maximum 1G\n", > + (unsigned int)(ram_size / (1024 * 1024))); > + exit(1); > + } > + > + ram_offset = qemu_ram_alloc(NULL, "leon3.ram", ram_size); > + cpu_register_physical_memory(0x40000000, ram_size, ram_offset | IO_MEM_RAM); > + > + /* Allocate BIOS */ > + prom_size = 8 * 1024 * 1024; /* 8Mb */ > + prom_offset = qemu_ram_alloc(NULL, "Leon3.bios", prom_size); > + cpu_register_physical_memory(0x00000000, prom_size, > + prom_offset | IO_MEM_ROM); > + > + /* Load boot prom */ > + if (bios_name == NULL) { > + bios_name = PROM_FILENAME; > + } > + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); > + > + bios_size = get_image_size(filename); > + > + if (bios_size > prom_size) { > + fprintf(stderr, "qemu: could not load prom '%s': file too big \n", > + filename); > + exit(1); > + } > + > + if (bios_size > 0) { > + aligned_bios_size = > + (bios_size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK; > + > + ret = load_image_targphys(filename, 0x00000000, bios_size); > + if (ret < 0 || ret > prom_size) { > + fprintf(stderr, "qemu: could not load prom '%s'\n", filename); > + exit(1); > + } > + } > + else if (kernel_filename == NULL) { > + fprintf(stderr,"Can't read bios image %s\n", filename); > + exit(1); > + } > + > + /* Can directly load an application. */ > + if (kernel_filename != NULL) { > + long kernel_size; > + uint64_t entry; > + > + kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL, > + 1 /* big endian */, ELF_MACHINE, 0); > + if (kernel_size < 0) { > + fprintf(stderr, "qemu: could not load kernel '%s'\n", > + kernel_filename); > + exit(1); > + } > + if (bios_size <= 0) { > + /* If there is no bios/monitor, start the application. */ > + env->pc = entry; > + env->npc = entry + 4; > + reset_info->entry = entry; > + } > + } > + > + /* Allocate timers */ > + grlib_gptimer_create(0x80000300, 2, CPU_CLK, cpu_irqs, 6); > + > + /* Allocate uart */ > + if (serial_hds[0]) { > + grlib_apbuart_create(0x80000100, serial_hds[0], cpu_irqs[3]); > + } > +} > + > +QEMUMachine leon3_generic_machine = { > + .name = "leon3_generic", > + .desc = "Leon-3 generic", > + .init = leon3_generic_hw_init, > + .use_scsi = 0, > +}; > + > +static void leon3_machine_init(void) > +{ > + qemu_register_machine(&leon3_generic_machine); > +} > + > +machine_init(leon3_machine_init); > diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h > index 7225b2e..5c50d9e 100644 > --- a/target-sparc/cpu.h > +++ b/target-sparc/cpu.h > @@ -252,20 +252,21 @@ typedef struct sparc_def_t { > uint32_t maxtl; > } sparc_def_t; > > -#define CPU_FEATURE_FLOAT (1 << 0) > -#define CPU_FEATURE_FLOAT128 (1 << 1) > -#define CPU_FEATURE_SWAP (1 << 2) > -#define CPU_FEATURE_MUL (1 << 3) > -#define CPU_FEATURE_DIV (1 << 4) > -#define CPU_FEATURE_FLUSH (1 << 5) > -#define CPU_FEATURE_FSQRT (1 << 6) > -#define CPU_FEATURE_FMUL (1 << 7) > -#define CPU_FEATURE_VIS1 (1 << 8) > -#define CPU_FEATURE_VIS2 (1 << 9) > -#define CPU_FEATURE_FSMULD (1 << 10) > -#define CPU_FEATURE_HYPV (1 << 11) > -#define CPU_FEATURE_CMT (1 << 12) > -#define CPU_FEATURE_GL (1 << 13) > +#define CPU_FEATURE_FLOAT (1 << 0) > +#define CPU_FEATURE_FLOAT128 (1 << 1) > +#define CPU_FEATURE_SWAP (1 << 2) > +#define CPU_FEATURE_MUL (1 << 3) > +#define CPU_FEATURE_DIV (1 << 4) > +#define CPU_FEATURE_FLUSH (1 << 5) > +#define CPU_FEATURE_FSQRT (1 << 6) > +#define CPU_FEATURE_FMUL (1 << 7) > +#define CPU_FEATURE_VIS1 (1 << 8) > +#define CPU_FEATURE_VIS2 (1 << 9) > +#define CPU_FEATURE_FSMULD (1 << 10) > +#define CPU_FEATURE_HYPV (1 << 11) > +#define CPU_FEATURE_CMT (1 << 12) > +#define CPU_FEATURE_GL (1 << 13) > +#define CPU_FEATURE_TA0_SHUTDOWN (1 << 14) /* Shutdown on "ta 0x0" */ > #ifndef TARGET_SPARC64 > #define CPU_DEFAULT_FEATURES (CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | \ > CPU_FEATURE_MUL | CPU_FEATURE_DIV | \ > @@ -437,6 +438,12 @@ typedef struct CPUSPARCState { > #define SOFTINT_REG_MASK (SOFTINT_STIMER|SOFTINT_INTRMASK|SOFTINT_TIMER) > #endif > sparc_def_t *def; > + > + void *irq_manager; > + void (*qemu_irq_ack) (void *irq_manager, int intno); > + > + /* Leon3 cache control */ > + uint32_t cache_control; > } CPUSPARCState; > > #ifndef NO_CPU_IO_DEFS > @@ -469,6 +476,8 @@ int cpu_cwp_inc(CPUState *env1, int cwp); > int cpu_cwp_dec(CPUState *env1, int cwp); > void cpu_set_cwp(CPUState *env1, int new_cwp); > > +void leon3_cache_control_int(void); > + > /* sun4m.c, sun4u.c */ > void cpu_check_irqs(CPUSPARCState *env); > > diff --git a/target-sparc/helper.c b/target-sparc/helper.c > index 6b337ca..ec6ac27 100644 > --- a/target-sparc/helper.c > +++ b/target-sparc/helper.c > @@ -770,6 +770,7 @@ void cpu_reset(CPUSPARCState *env) > env->pc = 0; > env->npc = env->pc + 4; > #endif > + env->cache_control = 0; > } > > static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model) > @@ -1274,20 +1275,20 @@ static const sparc_def_t sparc_defs[] = { > .mmu_sfsr_mask = 0xffffffff, > .mmu_trcr_mask = 0xffffffff, > .nwindows = 8, > - .features = CPU_DEFAULT_FEATURES, > + .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN, > }, > { > .name = "LEON3", > .iu_version = 0xf3000000, > .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */ > .mmu_version = 0xf3000000, > - .mmu_bm = 0x00004000, > + .mmu_bm = 0x00000000, > .mmu_ctpr_mask = 0x007ffff0, > .mmu_cxr_mask = 0x0000003f, > .mmu_sfsr_mask = 0xffffffff, > .mmu_trcr_mask = 0xffffffff, > .nwindows = 8, > - .features = CPU_DEFAULT_FEATURES, > + .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN, > }, > #endif > }; > diff --git a/target-sparc/helper.h b/target-sparc/helper.h > index e6d82f9..12e8557 100644 > --- a/target-sparc/helper.h > +++ b/target-sparc/helper.h > @@ -85,6 +85,7 @@ DEF_HELPER_0(fcmpeq_fcc2, void) > DEF_HELPER_0(fcmpeq_fcc3, void) > #endif > DEF_HELPER_1(raise_exception, void, int) > +DEF_HELPER_0(shutdown, void) > #define F_HELPER_0_0(name) DEF_HELPER_0(f ## name, void) > #define F_HELPER_DQ_0_0(name) \ > F_HELPER_0_0(name ## d); \ > diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c > index b70970a..66b7cdf 100644 > --- a/target-sparc/op_helper.c > +++ b/target-sparc/op_helper.c > @@ -1,6 +1,7 @@ > #include "exec.h" > #include "host-utils.h" > #include "helper.h" > +#include "sysemu.h" > > //#define DEBUG_MMU > //#define DEBUG_MXCC > @@ -9,6 +10,7 @@ > //#define DEBUG_ASI > //#define DEBUG_PCALL > //#define DEBUG_PSTATE > +//#define DEBUG_CACHE_CONTROL > > #ifdef DEBUG_MMU > #define DPRINTF_MMU(fmt, ...) \ > @@ -36,6 +38,13 @@ > #define DPRINTF_PSTATE(fmt, ...) do {} while (0) > #endif > > +#ifdef DEBUG_CACHE_CONTROL > +#define DPRINTF_CACHE_CONTROL(fmt, ...) \ > + do { printf("CACHE_CONTROL: " fmt , ## __VA_ARGS__); } while (0) > +#else > +#define DPRINTF_CACHE_CONTROL(fmt, ...) do {} while (0) > +#endif > + > #ifdef TARGET_SPARC64 > #ifndef TARGET_ABI32 > #define AM_CHECK(env1) ((env1)->pstate & PS_AM) > @@ -49,6 +58,27 @@ > #define QT0 (env->qt0) > #define QT1 (env->qt1) > > +/* Leon3 cache control */ > + > +/* Cache control: emulate the behavior of cache control registers but without > + any effect on the emulated */ > + > +#define CACHE_STATE_MASK 0x3 > +#define CACHE_DISABLED 0x0 > +#define CACHE_FROZEN 0x1 > +#define CACHE_ENABLED 0x3 > + > +/* Cache Control register fields */ > + > +#define CACHE_CTRL_IF (1 << 4) /* Instruction Cache Freeze on Interrupt */ > +#define CACHE_CTRL_DF (1 << 5) /* Data Cache Freeze on Interrupt */ > +#define CACHE_CTRL_DP (1 << 14) /* Data cache flush pending */ > +#define CACHE_CTRL_IP (1 << 15) /* Instruction cache flush pending */ > +#define CACHE_CTRL_IB (1 << 16) /* Instruction burst fetch */ > +#define CACHE_CTRL_FI (1 << 21) /* Flush Instruction cache (Write only) */ > +#define CACHE_CTRL_FD (1 << 22) /* Flush Data cache (Write only) */ > +#define CACHE_CTRL_DS (1 << 23) /* Data cache snoop enable */ > + > #if defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64) > static void do_unassigned_access(target_ulong addr, int is_write, int is_exec, > int is_asi, int size); > @@ -294,6 +324,11 @@ void HELPER(raise_exception)(int tt) > raise_exception(tt); > } > > +void helper_shutdown(void) > +{ > + qemu_system_shutdown_request(); This function is not available to user emulators: LINK sparc-linux-user/qemu-sparc op_helper.o: In function `helper_shutdown': /src/qemu/target-sparc/op_helper.c:329: undefined reference to `qemu_system_shutdown_request' Please surround it with #if !defined(CONFIG_USER_ONLY) #endif ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH v3 4/5] SPARC: Emulation of Leon3 2011-01-21 19:02 ` [Qemu-devel] [PATCH v3 4/5] SPARC: Emulation of Leon3 Blue Swirl @ 2011-01-21 19:09 ` Blue Swirl 0 siblings, 0 replies; 10+ messages in thread From: Blue Swirl @ 2011-01-21 19:09 UTC (permalink / raw) To: Fabien Chouteau; +Cc: qemu-devel On Fri, Jan 21, 2011 at 7:02 PM, Blue Swirl <blauwirbel@gmail.com> wrote: > On Fri, Jan 21, 2011 at 5:00 PM, Fabien Chouteau <chouteau@adacore.com> wrote: >> Leon3 is an open-source VHDL System-On-Chip, well known in space industry (more >> information on http://www.gaisler.com). >> >> Leon3 is made of multiple components available in the GrLib VHDL library. >> Three devices are implemented: uart, timers and IRQ manager. >> You can find code for these peripherals in the grlib_* files. >> >> Signed-off-by: Fabien Chouteau <chouteau@adacore.com> >> --- >> Makefile.target | 5 +- >> hw/leon3.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++ >> target-sparc/cpu.h | 37 +++++--- >> target-sparc/helper.c | 7 +- >> target-sparc/helper.h | 1 + >> target-sparc/op_helper.c | 154 ++++++++++++++++++++++++++++++- >> target-sparc/translate.c | 13 ++- >> 7 files changed, 426 insertions(+), 22 deletions(-) >> >> diff --git a/Makefile.target b/Makefile.target >> index e15b1c4..efd8406 100644 >> --- a/Makefile.target >> +++ b/Makefile.target >> @@ -286,7 +286,10 @@ obj-sparc-y += cirrus_vga.o >> else >> obj-sparc-y = sun4m.o lance.o tcx.o sun4m_iommu.o slavio_intctl.o >> obj-sparc-y += slavio_timer.o slavio_misc.o sparc32_dma.o >> -obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o >> +obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o leon3.o >> + >> +# GRLIB >> +obj-sparc-y += grlib_gptimer.o grlib_irqmp.o grlib_apbuart.o >> endif >> >> obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o >> diff --git a/hw/leon3.c b/hw/leon3.c >> new file mode 100644 >> index 0000000..f8f994a >> --- /dev/null >> +++ b/hw/leon3.c >> @@ -0,0 +1,231 @@ >> +/* >> + * QEMU Leon3 System Emulator >> + * >> + * Copyright (c) 2010-2011 AdaCore >> + * >> + * Permission is hereby granted, free of charge, to any person obtaining a copy >> + * of this software and associated documentation files (the "Software"), to deal >> + * in the Software without restriction, including without limitation the rights >> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell >> + * copies of the Software, and to permit persons to whom the Software is >> + * furnished to do so, subject to the following conditions: >> + * >> + * The above copyright notice and this permission notice shall be included in >> + * all copies or substantial portions of the Software. >> + * >> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR >> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, >> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL >> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER >> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, >> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN >> + * THE SOFTWARE. >> + */ >> +#include "hw.h" >> +#include "qemu-timer.h" >> +#include "qemu-char.h" >> +#include "sysemu.h" >> +#include "boards.h" >> +#include "loader.h" >> +#include "elf.h" >> + >> +#include "grlib.h" >> + >> +//#define DEBUG_LEON3 >> + >> +#ifdef DEBUG_LEON3 >> +#define DPRINTF(fmt, ...) \ >> + do { printf("Leon3: " fmt , ## __VA_ARGS__); } while (0) >> +#else >> +#define DPRINTF(fmt, ...) >> +#endif >> + >> +/* Default system clock. */ >> +#define CPU_CLK (40 * 1000 * 1000) >> + >> +#define PROM_FILENAME "u-boot.bin" >> + >> +#define MAX_PILS 16 >> + >> +typedef struct ResetData { >> + CPUState *env; >> + uint32_t entry; /* save kernel entry in case of reset */ >> +} ResetData; >> + >> +static void main_cpu_reset(void *opaque) >> +{ >> + ResetData *s = (ResetData *)opaque; >> + CPUState *env = s->env; >> + >> + cpu_reset(env); >> + >> + env->halted = 0; >> + env->pc = s->entry; >> + env->npc = s->entry + 4; >> +} >> + >> +static void leon3_irq_ack(void *irq_manager, int intno) >> +{ >> + grlib_irqmp_ack((DeviceState *)irq_manager, intno); >> + leon3_cache_control_int(); >> +} >> + >> +static void leon3_set_pil_in(void *opaque, uint32_t pil_in) >> +{ >> + CPUState *env = (CPUState *)opaque; >> + >> + assert(env != NULL); >> + >> + env->pil_in = pil_in; >> + >> + if (env->pil_in && (env->interrupt_index == 0 || >> + (env->interrupt_index & ~15) == TT_EXTINT)) { >> + unsigned int i; >> + >> + for (i = 15; i > 0; i--) { >> + if (env->pil_in & (1 << i)) { >> + int old_interrupt = env->interrupt_index; >> + >> + env->interrupt_index = TT_EXTINT | i; >> + if (old_interrupt != env->interrupt_index) { >> + DPRINTF("Set CPU IRQ %d\n", i); >> + cpu_interrupt(env, CPU_INTERRUPT_HARD); >> + } >> + break; >> + } >> + } >> + } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) { >> + DPRINTF("Reset CPU IRQ %d\n", env->interrupt_index & 15); >> + env->interrupt_index = 0; >> + cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); >> + } >> +} >> + >> +static void leon3_generic_hw_init(ram_addr_t ram_size, >> + const char *boot_device, >> + const char *kernel_filename, >> + const char *kernel_cmdline, >> + const char *initrd_filename, >> + const char *cpu_model) >> +{ >> + CPUState *env; >> + ram_addr_t ram_offset, prom_offset; >> + int ret; >> + char *filename; >> + qemu_irq *cpu_irqs = NULL; >> + int bios_size; >> + int prom_size; >> + int aligned_bios_size; GCC 4.6.0 spotted this one: /src/qemu/hw/leon3.c: In function 'leon3_generic_hw_init': /src/qemu/hw/leon3.c:118:17: error: variable 'aligned_bios_size' set but not used [-Werror=unused-but-set-variable] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH v3 0/5][RFC] New SPARC machine: Leon3 2011-01-21 17:00 [Qemu-devel] [PATCH v3 0/5][RFC] New SPARC machine: Leon3 Fabien Chouteau 2011-01-21 17:00 ` [Qemu-devel] [PATCH v3 1/5] SPARC: Emulation of GRLIB GPTimer Fabien Chouteau @ 2011-01-21 19:04 ` Blue Swirl 2011-01-24 10:24 ` Fabien Chouteau 1 sibling, 1 reply; 10+ messages in thread From: Blue Swirl @ 2011-01-21 19:04 UTC (permalink / raw) To: Fabien Chouteau; +Cc: qemu-devel On Fri, Jan 21, 2011 at 5:00 PM, Fabien Chouteau <chouteau@adacore.com> wrote: > Hello Qemu-devel, > > Here is the third version of Leon3 emulation patch-set. > > Modifications since v2: > - Tracepoints > - DEFINE_PROP_* macros > - New interface to trigger interrupts on Leon3 (set_pil_in:leon3.c) > - Minor reformating > > Please feel free to comment. The patches look fine to me now, except 4/5 had a small problem. Could you run them through checkpatch.pl and fix the issues? The lines like //#define DEBUG_LEON3 can stay despite the error if you don't convert them to tracepoints. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH v3 0/5][RFC] New SPARC machine: Leon3 2011-01-21 19:04 ` [Qemu-devel] [PATCH v3 0/5][RFC] New SPARC machine: Leon3 Blue Swirl @ 2011-01-24 10:24 ` Fabien Chouteau 0 siblings, 0 replies; 10+ messages in thread From: Fabien Chouteau @ 2011-01-24 10:24 UTC (permalink / raw) To: Blue Swirl; +Cc: qemu-devel On 01/21/2011 08:04 PM, Blue Swirl wrote: > On Fri, Jan 21, 2011 at 5:00 PM, Fabien Chouteau<chouteau@adacore.com> wrote: >> Hello Qemu-devel, >> >> Here is the third version of Leon3 emulation patch-set. >> >> Modifications since v2: >> - Tracepoints >> - DEFINE_PROP_* macros >> - New interface to trigger interrupts on Leon3 (set_pil_in:leon3.c) >> - Minor reformating >> >> Please feel free to comment. > > The patches look fine to me now, except 4/5 had a small problem. > > Could you run them through checkpatch.pl and fix the issues? The lines > like //#define DEBUG_LEON3 can stay despite the error if you don't > convert them to tracepoints. Sure, I will fix the two problems that you pointed out and run checkpatch.pl to fix the remaining style issues. -- Fabien Chouteau ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-01-24 10:25 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-01-21 17:00 [Qemu-devel] [PATCH v3 0/5][RFC] New SPARC machine: Leon3 Fabien Chouteau 2011-01-21 17:00 ` [Qemu-devel] [PATCH v3 1/5] SPARC: Emulation of GRLIB GPTimer Fabien Chouteau 2011-01-21 17:00 ` [Qemu-devel] [PATCH v3 2/5] SPARC: Emulation of GRLIB IRQMP Fabien Chouteau 2011-01-21 17:00 ` [Qemu-devel] [PATCH v3 3/5] SPARC: Emulation of GRLIB APB UART Fabien Chouteau 2011-01-21 17:00 ` [Qemu-devel] [PATCH v3 4/5] SPARC: Emulation of Leon3 Fabien Chouteau 2011-01-21 17:00 ` [Qemu-devel] [PATCH v3 5/5] SPARC: Add asr17 register support Fabien Chouteau 2011-01-21 19:02 ` [Qemu-devel] [PATCH v3 4/5] SPARC: Emulation of Leon3 Blue Swirl 2011-01-21 19:09 ` Blue Swirl 2011-01-21 19:04 ` [Qemu-devel] [PATCH v3 0/5][RFC] New SPARC machine: Leon3 Blue Swirl 2011-01-24 10:24 ` Fabien Chouteau
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).