New SPARC machine: Leon3
v3 cover New SPARC machine: Leon3
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
PATCH v3 1/5 SPARC: Emulation of GRLIB GPTimer
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
--- hw/grlib.h | 65 +++++++++ hw/grlib_gptimer.c | 401 ++++++++++++++++++++++++++++++++++++++++++++++++++++ trace-events | 10 ++ 3 files changed, 476 insertions(+), 0 deletions(-)
hw/grlib.h new file +65 -0
@@ -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_ */
hw/grlib_gptimer.c new file +401 -0
401 lines not on this page · raw message
trace-events +10 -0
@@ -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""
Signature · 1 line
1.7.1
PATCH v3 2/5 SPARC: Emulation of GRLIB IRQMP
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
--- hw/grlib.h | 38 ++++++ hw/grlib_irqmp.c | 380 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ trace-events | 6 + 3 files changed, 424 insertions(+), 0 deletions(-)
hw/grlib.h +38 -0
@@ -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
hw/grlib_irqmp.c new file +380 -0
380 lines not on this page · raw message
trace-events +6 -0
@@ -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""
Signature · 1 line
1.7.1
PATCH v3 3/5 SPARC: Emulation of GRLIB APB UART
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
--- hw/grlib.h | 23 ++++++ hw/grlib_apbuart.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++++++++ trace-events | 4 + 3 files changed, 216 insertions(+), 0 deletions(-)
hw/grlib.h +23 -0
@@ -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_ */
hw/grlib_apbuart.c new file +189 -0
189 lines not on this page · raw message
trace-events +4 -0
@@ -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""
Signature · 1 line
1.7.1
PATCH v3 4/5 SPARC: Emulation of Leon3
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.
--- 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(-)
Makefile.target +4 -1
@@ -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
hw/leon3.c new file +231 -0
231 lines not on this page · raw message
target-sparc/cpu.h +23 -14
@@ -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);
target-sparc/helper.c +4 -3
@@ -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 };
target-sparc/helper.h +1 -0
@@ -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); \
target-sparc/op_helper.c +152 -2
210 lines not on this page · raw message
target-sparc/translate.c +11 -2
@@ -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;
Signature · 1 line
1.7.1
PATCH v3 5/5 SPARC: Add asr17 register support
This register is activated by CPU_FEATURE_ASR17 in the feature field.
--- target-sparc/cpu.h | 1 + target-sparc/helper.c | 3 ++- target-sparc/translate.c | 11 +++++++++++ 3 files changed, 14 insertions(+), 1 deletions(-)
target-sparc/cpu.h +1 -0
@@ -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 | \
target-sparc/helper.c +2 -1
@@ -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 };
target-sparc/translate.c +11 -0
@@ -2067,6 +2067,17 @@ static void disas_sparc_insn(DisasContext * dc) case 0x10 ... 0x1f: /* implementation-dependent in theSPARCv8 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 ;
Signature · 1 line
1.7.1
Re: [Qemu-devel] [PATCH v3 4/5] SPARC: Emulation of Leon3
In reply to Fabien ChouteauQuoted 444 lines · 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 <[email protected]>---
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(-)Makefile.target +0
-0@@ -286,7 +286,10 @@ obj-sparc-y += cirrus_vga.oelse
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.oMakefile.target +4
-1-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.oendif
obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
hw/leon3.c new file +231
-0@@ -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);target-sparc/cpu.h +23
-14@@ -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);target-sparc/helper.c +2
-1@@ -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
};target-sparc/helper.h +1
-0@@ -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); \target-sparc/op_helper.c +30
-0@@ -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);
target-sparc/op_helper.c void HELPER(raise_exception)(int tt) · line 329
Quoted 6 lines
target-sparc/op_helper.c +3
-0@@ -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
Re: [Qemu-devel] [PATCH v3 4/5] SPARC: Emulation of Leon3
Quoted 151 lines · Blue Swirl
Quoted 150 lines · 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 <[email protected]>---
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(-)Makefile.target +0
-0@@ -286,7 +286,10 @@ obj-sparc-y += cirrus_vga.oelse
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.oMakefile.target +4
-1-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.oendif
obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
hw/leon3.c new file +110
-0@@ -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) +{
Quoted 8 lines
hw/leon3.c line 118
Quoted 8 lines
hw/leon3.c new file +8
-0+ 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]
Quoted 11 lines · 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 reformatingPlease 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.
Quoted 11 lines · Blue Swirl
Quoted 10 lines · 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
Quoted 7 lines
Quoted 1 line
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_LEON3can 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.
Signature · 1 line
Fabien Chouteau