Commit e62b5b133b97e07711741e2a4e2bf3e4dbc254f8
1 parent
1ec6d2ea
* Add a model of the ETRAX interrupt controller.
* Clean up the interrupt handling a bit. * Connect some NOR flash to the test board. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4055 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
8 changed files
with
323 additions
and
179 deletions
Makefile.target
@@ -565,9 +565,12 @@ CPPFLAGS += -DHAS_AUDIO | @@ -565,9 +565,12 @@ CPPFLAGS += -DHAS_AUDIO | ||
565 | endif | 565 | endif |
566 | ifeq ($(TARGET_BASE_ARCH), cris) | 566 | ifeq ($(TARGET_BASE_ARCH), cris) |
567 | OBJS+= etraxfs.o | 567 | OBJS+= etraxfs.o |
568 | -OBJS+= ptimer.o | 568 | +OBJS+= etraxfs_pic.o |
569 | OBJS+= etraxfs_timer.o | 569 | OBJS+= etraxfs_timer.o |
570 | OBJS+= etraxfs_ser.o | 570 | OBJS+= etraxfs_ser.o |
571 | + | ||
572 | +OBJS+= ptimer.o | ||
573 | +OBJS+= pflash_cfi01.o | ||
571 | endif | 574 | endif |
572 | ifeq ($(TARGET_BASE_ARCH), sparc) | 575 | ifeq ($(TARGET_BASE_ARCH), sparc) |
573 | ifeq ($(TARGET_ARCH), sparc64) | 576 | ifeq ($(TARGET_ARCH), sparc64) |
cpu-exec.c
@@ -556,7 +556,6 @@ int cpu_exec(CPUState *env1) | @@ -556,7 +556,6 @@ int cpu_exec(CPUState *env1) | ||
556 | #elif defined(TARGET_CRIS) | 556 | #elif defined(TARGET_CRIS) |
557 | if (interrupt_request & CPU_INTERRUPT_HARD) { | 557 | if (interrupt_request & CPU_INTERRUPT_HARD) { |
558 | do_interrupt(env); | 558 | do_interrupt(env); |
559 | - env->interrupt_request &= ~CPU_INTERRUPT_HARD; | ||
560 | BREAK_CHAIN; | 559 | BREAK_CHAIN; |
561 | } | 560 | } |
562 | #elif defined(TARGET_M68K) | 561 | #elif defined(TARGET_M68K) |
@@ -1181,10 +1180,6 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | @@ -1181,10 +1180,6 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | ||
1181 | a virtual CPU fault */ | 1180 | a virtual CPU fault */ |
1182 | cpu_restore_state(tb, env, pc, puc); | 1181 | cpu_restore_state(tb, env, pc, puc); |
1183 | } | 1182 | } |
1184 | -#if 0 | ||
1185 | - printf("PF exception: NIP=0x%08x error=0x%x %p\n", | ||
1186 | - env->nip, env->error_code, tb); | ||
1187 | -#endif | ||
1188 | /* we restore the process signal mask as the sigreturn should | 1183 | /* we restore the process signal mask as the sigreturn should |
1189 | do it (XXX: use sigsetjmp) */ | 1184 | do it (XXX: use sigsetjmp) */ |
1190 | sigprocmask(SIG_SETMASK, old_set, NULL); | 1185 | sigprocmask(SIG_SETMASK, old_set, NULL); |
hw/etraxfs.c
@@ -25,89 +25,21 @@ | @@ -25,89 +25,21 @@ | ||
25 | #include <sys/time.h> | 25 | #include <sys/time.h> |
26 | #include "hw.h" | 26 | #include "hw.h" |
27 | #include "sysemu.h" | 27 | #include "sysemu.h" |
28 | +#include "flash.h" | ||
28 | #include "boards.h" | 29 | #include "boards.h" |
29 | 30 | ||
30 | -extern FILE *logfile; | ||
31 | - | ||
32 | static void main_cpu_reset(void *opaque) | 31 | static void main_cpu_reset(void *opaque) |
33 | { | 32 | { |
34 | CPUState *env = opaque; | 33 | CPUState *env = opaque; |
35 | cpu_reset(env); | 34 | cpu_reset(env); |
36 | } | 35 | } |
37 | 36 | ||
38 | -static uint32_t fs_mmio_readb (void *opaque, target_phys_addr_t addr) | ||
39 | -{ | ||
40 | - CPUState *env = opaque; | ||
41 | - uint32_t r = 0; | ||
42 | - printf ("%s %x pc=%x\n", __func__, addr, env->pc); | ||
43 | - return r; | ||
44 | -} | ||
45 | -static uint32_t fs_mmio_readw (void *opaque, target_phys_addr_t addr) | ||
46 | -{ | ||
47 | - CPUState *env = opaque; | ||
48 | - uint32_t r = 0; | ||
49 | - printf ("%s %x pc=%x\n", __func__, addr, env->pc); | ||
50 | - return r; | ||
51 | -} | ||
52 | - | ||
53 | -static uint32_t fs_mmio_readl (void *opaque, target_phys_addr_t addr) | ||
54 | -{ | ||
55 | - CPUState *env = opaque; | ||
56 | - uint32_t r = 0; | ||
57 | - printf ("%s %x p=%x\n", __func__, addr, env->pc); | ||
58 | - return r; | ||
59 | -} | ||
60 | - | ||
61 | -static void | ||
62 | -fs_mmio_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
63 | -{ | ||
64 | - CPUState *env = opaque; | ||
65 | - printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); | ||
66 | -} | ||
67 | -static void | ||
68 | -fs_mmio_writew (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
69 | -{ | ||
70 | - CPUState *env = opaque; | ||
71 | - printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); | ||
72 | -} | ||
73 | -static void | ||
74 | -fs_mmio_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
75 | -{ | ||
76 | - CPUState *env = opaque; | ||
77 | - printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); | ||
78 | -} | ||
79 | - | ||
80 | -static CPUReadMemoryFunc *fs_mmio_read[] = { | ||
81 | - &fs_mmio_readb, | ||
82 | - &fs_mmio_readw, | ||
83 | - &fs_mmio_readl, | ||
84 | -}; | ||
85 | - | ||
86 | -static CPUWriteMemoryFunc *fs_mmio_write[] = { | ||
87 | - &fs_mmio_writeb, | ||
88 | - &fs_mmio_writew, | ||
89 | - &fs_mmio_writel, | ||
90 | -}; | ||
91 | - | ||
92 | - | ||
93 | /* Init functions for different blocks. */ | 37 | /* Init functions for different blocks. */ |
38 | +extern qemu_irq *etraxfs_pic_init(CPUState *env, target_ulong base); | ||
39 | +/* TODO: Make these blocks relocate:able. */ | ||
94 | extern void etraxfs_timer_init(CPUState *env, qemu_irq *irqs); | 40 | extern void etraxfs_timer_init(CPUState *env, qemu_irq *irqs); |
95 | extern void etraxfs_ser_init(CPUState *env, qemu_irq *irqs); | 41 | extern void etraxfs_ser_init(CPUState *env, qemu_irq *irqs); |
96 | 42 | ||
97 | -void etrax_ack_irq(CPUState *env, uint32_t mask) | ||
98 | -{ | ||
99 | - env->pending_interrupts &= ~mask; | ||
100 | -} | ||
101 | - | ||
102 | -static void dummy_cpu_set_irq(void *opaque, int irq, int level) | ||
103 | -{ | ||
104 | - CPUState *env = opaque; | ||
105 | - | ||
106 | - /* Hmm, should this really be done here? */ | ||
107 | - env->pending_interrupts |= 1 << irq; | ||
108 | - cpu_interrupt(env, CPU_INTERRUPT_HARD); | ||
109 | -} | ||
110 | - | ||
111 | static | 43 | static |
112 | void bareetraxfs_init (int ram_size, int vga_ram_size, | 44 | void bareetraxfs_init (int ram_size, int vga_ram_size, |
113 | const char *boot_device, DisplayState *ds, | 45 | const char *boot_device, DisplayState *ds, |
@@ -115,9 +47,12 @@ void bareetraxfs_init (int ram_size, int vga_ram_size, | @@ -115,9 +47,12 @@ void bareetraxfs_init (int ram_size, int vga_ram_size, | ||
115 | const char *initrd_filename, const char *cpu_model) | 47 | const char *initrd_filename, const char *cpu_model) |
116 | { | 48 | { |
117 | CPUState *env; | 49 | CPUState *env; |
118 | - qemu_irq *irqs; | 50 | + qemu_irq *pic; |
119 | int kernel_size; | 51 | int kernel_size; |
120 | - int internal_regs; | 52 | + int flash_size = 0x800000; |
53 | + int index; | ||
54 | + ram_addr_t phys_flash; | ||
55 | + ram_addr_t phys_ram; | ||
121 | 56 | ||
122 | /* init CPUs */ | 57 | /* init CPUs */ |
123 | if (cpu_model == NULL) { | 58 | if (cpu_model == NULL) { |
@@ -126,17 +61,31 @@ void bareetraxfs_init (int ram_size, int vga_ram_size, | @@ -126,17 +61,31 @@ void bareetraxfs_init (int ram_size, int vga_ram_size, | ||
126 | env = cpu_init(cpu_model); | 61 | env = cpu_init(cpu_model); |
127 | /* register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); */ | 62 | /* register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); */ |
128 | qemu_register_reset(main_cpu_reset, env); | 63 | qemu_register_reset(main_cpu_reset, env); |
129 | - irqs = qemu_allocate_irqs(dummy_cpu_set_irq, env, 32); | ||
130 | 64 | ||
131 | - internal_regs = cpu_register_io_memory(0, | ||
132 | - fs_mmio_read, fs_mmio_write, env); | ||
133 | - /* 0xb0050000 is the last reg. */ | ||
134 | - cpu_register_physical_memory (0xac000000, 0x4010000, internal_regs); | ||
135 | /* allocate RAM */ | 65 | /* allocate RAM */ |
136 | - cpu_register_physical_memory(0x40000000, ram_size, IO_MEM_RAM); | ||
137 | - | ||
138 | - etraxfs_timer_init(env, irqs); | ||
139 | - etraxfs_ser_init(env, irqs); | 66 | + phys_ram = qemu_ram_alloc(ram_size); |
67 | + cpu_register_physical_memory(0x40000000, ram_size, phys_ram | IO_MEM_RAM); | ||
68 | + /* Unached mapping. */ | ||
69 | + cpu_register_physical_memory(0xc0000000, ram_size, phys_ram | IO_MEM_RAM); | ||
70 | + | ||
71 | + phys_flash = qemu_ram_alloc(flash_size); | ||
72 | + cpu_register_physical_memory(0,flash_size, IO_MEM_ROM); | ||
73 | + cpu_register_physical_memory(0x80000000, flash_size, IO_MEM_ROM); | ||
74 | + cpu_register_physical_memory(0x04000000, flash_size, IO_MEM_ROM); | ||
75 | + cpu_register_physical_memory(0x84000000, flash_size, | ||
76 | + 0x04000000 | IO_MEM_ROM); | ||
77 | + index = drive_get_index(IF_PFLASH, 0, 0); | ||
78 | + pflash_cfi01_register(0x80000000, flash_size, | ||
79 | + drives_table[index].bdrv, 65536, flash_size >> 16, | ||
80 | + 4, 0x0000, 0x0000, 0x0000, 0x0000); | ||
81 | + index = drive_get_index(IF_PFLASH, 0, 1); | ||
82 | + pflash_cfi01_register(0x84000000, flash_size, | ||
83 | + drives_table[index].bdrv, 65536, flash_size >> 16, | ||
84 | + 4, 0x0000, 0x0000, 0x0000, 0x0000); | ||
85 | + | ||
86 | + pic = etraxfs_pic_init(env, 0xb001c000); | ||
87 | + etraxfs_timer_init(env, pic); | ||
88 | + etraxfs_ser_init(env, pic); | ||
140 | 89 | ||
141 | kernel_size = load_image(kernel_filename, phys_ram_base + 0x4000); | 90 | kernel_size = load_image(kernel_filename, phys_ram_base + 0x4000); |
142 | /* magic for boot. */ | 91 | /* magic for boot. */ |
@@ -165,14 +114,6 @@ void DMA_run(void) | @@ -165,14 +114,6 @@ void DMA_run(void) | ||
165 | { | 114 | { |
166 | } | 115 | } |
167 | 116 | ||
168 | -void pic_info() | ||
169 | -{ | ||
170 | -} | ||
171 | - | ||
172 | -void irq_info() | ||
173 | -{ | ||
174 | -} | ||
175 | - | ||
176 | QEMUMachine bareetraxfs_machine = { | 117 | QEMUMachine bareetraxfs_machine = { |
177 | "bareetraxfs", | 118 | "bareetraxfs", |
178 | "Bare ETRAX FS board", | 119 | "Bare ETRAX FS board", |
hw/etraxfs_pic.c
0 โ 100644
1 | +/* | ||
2 | + * QEMU ETRAX Interrupt Controller. | ||
3 | + * | ||
4 | + * Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB. | ||
5 | + * | ||
6 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
7 | + * of this software and associated documentation files (the "Software"), to deal | ||
8 | + * in the Software without restriction, including without limitation the rights | ||
9 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
10 | + * copies of the Software, and to permit persons to whom the Software is | ||
11 | + * furnished to do so, subject to the following conditions: | ||
12 | + * | ||
13 | + * The above copyright notice and this permission notice shall be included in | ||
14 | + * all copies or substantial portions of the Software. | ||
15 | + * | ||
16 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
19 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
21 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
22 | + * THE SOFTWARE. | ||
23 | + */ | ||
24 | + | ||
25 | +#include <stdio.h> | ||
26 | +#include "hw.h" | ||
27 | + | ||
28 | +#define D(x) | ||
29 | + | ||
30 | +struct fs_pic_state_t | ||
31 | +{ | ||
32 | + CPUState *env; | ||
33 | + target_ulong base; | ||
34 | + | ||
35 | + uint32_t rw_mask; | ||
36 | + /* Active interrupt lines. */ | ||
37 | + uint32_t r_vect; | ||
38 | + /* Active lines, gated through the mask. */ | ||
39 | + uint32_t r_masked_vect; | ||
40 | + uint32_t r_nmi; | ||
41 | + uint32_t r_guru; | ||
42 | +}; | ||
43 | + | ||
44 | +static uint32_t pic_readb (void *opaque, target_phys_addr_t addr) | ||
45 | +{ | ||
46 | + return 0; | ||
47 | +} | ||
48 | +static uint32_t pic_readw (void *opaque, target_phys_addr_t addr) | ||
49 | +{ | ||
50 | + return 0; | ||
51 | +} | ||
52 | + | ||
53 | +static uint32_t pic_readl (void *opaque, target_phys_addr_t addr) | ||
54 | +{ | ||
55 | + struct fs_pic_state_t *fs = opaque; | ||
56 | + uint32_t rval; | ||
57 | + | ||
58 | + /* Transform this to a relative addr. */ | ||
59 | + addr -= fs->base; | ||
60 | + switch (addr) | ||
61 | + { | ||
62 | + case 0x0: | ||
63 | + rval = fs->rw_mask; | ||
64 | + break; | ||
65 | + case 0x4: | ||
66 | + rval = fs->r_vect; | ||
67 | + break; | ||
68 | + case 0x8: | ||
69 | + rval = fs->r_masked_vect; | ||
70 | + break; | ||
71 | + case 0xc: | ||
72 | + rval = fs->r_nmi; | ||
73 | + break; | ||
74 | + case 0x10: | ||
75 | + rval = fs->r_guru; | ||
76 | + break; | ||
77 | + default: | ||
78 | + cpu_abort(fs->env, "invalid PIC register.\n"); | ||
79 | + break; | ||
80 | + | ||
81 | + } | ||
82 | + D(printf("%s %x=%x\n", __func__, addr, rval)); | ||
83 | + return rval; | ||
84 | +} | ||
85 | + | ||
86 | +static void | ||
87 | +pic_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
88 | +{ | ||
89 | +} | ||
90 | + | ||
91 | +static void | ||
92 | +pic_writew (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
93 | +{ | ||
94 | +} | ||
95 | + | ||
96 | +static void | ||
97 | +pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
98 | +{ | ||
99 | + struct fs_pic_state_t *fs = opaque; | ||
100 | + D(printf("%s addr=%x val=%x\n", __func__, addr, value)); | ||
101 | + /* Transform this to a relative addr. */ | ||
102 | + addr -= fs->base; | ||
103 | + switch (addr) | ||
104 | + { | ||
105 | + case 0x0: | ||
106 | + fs->rw_mask = value; | ||
107 | + break; | ||
108 | + case 0x4: | ||
109 | + fs->r_vect = value; | ||
110 | + break; | ||
111 | + case 0x8: | ||
112 | + fs->r_masked_vect = value; | ||
113 | + break; | ||
114 | + case 0xc: | ||
115 | + fs->r_nmi = value; | ||
116 | + break; | ||
117 | + case 0x10: | ||
118 | + fs->r_guru = value; | ||
119 | + break; | ||
120 | + default: | ||
121 | + cpu_abort(fs->env, "invalid PIC register.\n"); | ||
122 | + break; | ||
123 | + } | ||
124 | +} | ||
125 | + | ||
126 | +static CPUReadMemoryFunc *pic_read[] = { | ||
127 | + &pic_readb, | ||
128 | + &pic_readw, | ||
129 | + &pic_readl, | ||
130 | +}; | ||
131 | + | ||
132 | +static CPUWriteMemoryFunc *pic_write[] = { | ||
133 | + &pic_writeb, | ||
134 | + &pic_writew, | ||
135 | + &pic_writel, | ||
136 | +}; | ||
137 | + | ||
138 | +void pic_info(void) | ||
139 | +{ | ||
140 | +} | ||
141 | + | ||
142 | +void irq_info(void) | ||
143 | +{ | ||
144 | +} | ||
145 | + | ||
146 | +static void etraxfs_pic_handler(void *opaque, int irq, int level) | ||
147 | +{ | ||
148 | + struct fs_pic_state_t *fs = (void *)opaque; | ||
149 | + CPUState *env = fs->env; | ||
150 | + int i; | ||
151 | + uint32_t vector = 0; | ||
152 | + | ||
153 | + D(printf("%s irq=%d level=%d mask=%x v=%x mv=%x\n", | ||
154 | + __func__, irq, level, | ||
155 | + fs->rw_mask, fs->r_vect, fs->r_masked_vect)); | ||
156 | + | ||
157 | + fs->r_vect &= ~(1 << irq); | ||
158 | + fs->r_vect |= (!!level << irq); | ||
159 | + fs->r_masked_vect = fs->r_vect & fs->rw_mask; | ||
160 | + | ||
161 | + /* The ETRAX interrupt controller signals interrupts to teh core | ||
162 | + through an interrupt request wire and an irq vector bus. If | ||
163 | + multiple interrupts are simultaneously active it chooses vector | ||
164 | + 0x30 and lets the sw choose the priorities. */ | ||
165 | + if (fs->r_masked_vect) { | ||
166 | + uint32_t mv = fs->r_masked_vect; | ||
167 | + for (i = 0; i < 31; i++) { | ||
168 | + if (mv & 1) { | ||
169 | + vector = 0x31 + i; | ||
170 | + /* Check for multiple interrupts. */ | ||
171 | + if (mv > 1) | ||
172 | + vector = 0x30; | ||
173 | + break; | ||
174 | + } | ||
175 | + mv >>= 1; | ||
176 | + } | ||
177 | + if (vector) { | ||
178 | + env->interrupt_vector = vector; | ||
179 | + D(printf("%s vector=%x\n", __func__, vector)); | ||
180 | + cpu_interrupt(env, CPU_INTERRUPT_HARD); | ||
181 | + } | ||
182 | + } else { | ||
183 | + env->interrupt_vector = 0; | ||
184 | + cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); | ||
185 | + D(printf("%s reset irqs\n", __func__)); | ||
186 | + } | ||
187 | +} | ||
188 | + | ||
189 | +qemu_irq *etraxfs_pic_init(CPUState *env, target_ulong base) | ||
190 | +{ | ||
191 | + struct fs_pic_state_t *fs; | ||
192 | + qemu_irq *pic; | ||
193 | + int intr_vect_regs; | ||
194 | + | ||
195 | + fs = qemu_mallocz(sizeof *fs); | ||
196 | + if (!fs) | ||
197 | + return NULL; | ||
198 | + fs->env = env; | ||
199 | + | ||
200 | + pic = qemu_allocate_irqs(etraxfs_pic_handler, fs, 30); | ||
201 | + | ||
202 | + intr_vect_regs = cpu_register_io_memory(0, pic_read, pic_write, fs); | ||
203 | + cpu_register_physical_memory(base, 0x14, intr_vect_regs); | ||
204 | + fs->base = base; | ||
205 | + | ||
206 | + return pic; | ||
207 | +} |
hw/etraxfs_ser.c
@@ -66,7 +66,7 @@ static uint32_t ser_readl (void *opaque, target_phys_addr_t addr) | @@ -66,7 +66,7 @@ static uint32_t ser_readl (void *opaque, target_phys_addr_t addr) | ||
66 | break; | 66 | break; |
67 | 67 | ||
68 | default: | 68 | default: |
69 | - printf ("%s %x p=%x\n", __func__, addr, env->pc); | 69 | + D(printf ("%s %x p=%x\n", __func__, addr, env->pc)); |
70 | break; | 70 | break; |
71 | } | 71 | } |
72 | return r; | 72 | return r; |
@@ -100,10 +100,11 @@ ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | @@ -100,10 +100,11 @@ ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
100 | putchar(value); | 100 | putchar(value); |
101 | else | 101 | else |
102 | putchar('.'); | 102 | putchar('.'); |
103 | + fflush(stdout); | ||
103 | break; | 104 | break; |
104 | default: | 105 | default: |
105 | - printf ("%s %x %x pc=%x\n", | ||
106 | - __func__, addr, value, env->pc); | 106 | + D(printf ("%s %x %x pc=%x\n", |
107 | + __func__, addr, value, env->pc)); | ||
107 | break; | 108 | break; |
108 | } | 109 | } |
109 | } | 110 | } |
hw/etraxfs_timer.c
1 | /* | 1 | /* |
2 | - * QEMU ETRAX System Emulator | 2 | + * QEMU ETRAX Timers |
3 | * | 3 | * |
4 | * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB. | 4 | * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB. |
5 | * | 5 | * |
@@ -28,8 +28,6 @@ | @@ -28,8 +28,6 @@ | ||
28 | 28 | ||
29 | #define D(x) | 29 | #define D(x) |
30 | 30 | ||
31 | -void etrax_ack_irq(CPUState *env, uint32_t mask); | ||
32 | - | ||
33 | #define R_TIME 0xb001e038 | 31 | #define R_TIME 0xb001e038 |
34 | #define RW_TMR0_DIV 0xb001e000 | 32 | #define RW_TMR0_DIV 0xb001e000 |
35 | #define R_TMR0_DATA 0xb001e004 | 33 | #define R_TMR0_DATA 0xb001e004 |
@@ -38,16 +36,12 @@ void etrax_ack_irq(CPUState *env, uint32_t mask); | @@ -38,16 +36,12 @@ void etrax_ack_irq(CPUState *env, uint32_t mask); | ||
38 | #define R_TMR1_DATA 0xb001e014 | 36 | #define R_TMR1_DATA 0xb001e014 |
39 | #define RW_TMR1_CTRL 0xb001e018 | 37 | #define RW_TMR1_CTRL 0xb001e018 |
40 | 38 | ||
39 | +#define RW_WD_CTRL 0xb001e040 | ||
41 | #define RW_INTR_MASK 0xb001e048 | 40 | #define RW_INTR_MASK 0xb001e048 |
42 | #define RW_ACK_INTR 0xb001e04c | 41 | #define RW_ACK_INTR 0xb001e04c |
43 | #define R_INTR 0xb001e050 | 42 | #define R_INTR 0xb001e050 |
44 | #define R_MASKED_INTR 0xb001e054 | 43 | #define R_MASKED_INTR 0xb001e054 |
45 | 44 | ||
46 | - | ||
47 | -uint32_t rw_intr_mask; | ||
48 | -uint32_t rw_ack_intr; | ||
49 | -uint32_t r_intr; | ||
50 | - | ||
51 | struct fs_timer_t { | 45 | struct fs_timer_t { |
52 | QEMUBH *bh; | 46 | QEMUBH *bh; |
53 | unsigned int limit; | 47 | unsigned int limit; |
@@ -57,6 +51,10 @@ struct fs_timer_t { | @@ -57,6 +51,10 @@ struct fs_timer_t { | ||
57 | qemu_irq *irq; | 51 | qemu_irq *irq; |
58 | uint32_t mask; | 52 | uint32_t mask; |
59 | struct timeval last; | 53 | struct timeval last; |
54 | + | ||
55 | + uint32_t rw_intr_mask; | ||
56 | + uint32_t rw_ack_intr; | ||
57 | + uint32_t r_intr; | ||
60 | }; | 58 | }; |
61 | 59 | ||
62 | static struct fs_timer_t timer[2]; | 60 | static struct fs_timer_t timer[2]; |
@@ -126,13 +124,13 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) | @@ -126,13 +124,13 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) | ||
126 | } | 124 | } |
127 | 125 | ||
128 | case RW_INTR_MASK: | 126 | case RW_INTR_MASK: |
129 | - r = rw_intr_mask; | 127 | + r = timer[t].rw_intr_mask; |
130 | break; | 128 | break; |
131 | case R_MASKED_INTR: | 129 | case R_MASKED_INTR: |
132 | - r = r_intr & rw_intr_mask; | 130 | + r = timer[t].r_intr & timer[t].rw_intr_mask; |
133 | break; | 131 | break; |
134 | default: | 132 | default: |
135 | - printf ("%s %x p=%x\n", __func__, addr, env->pc); | 133 | + D(printf ("%s %x p=%x\n", __func__, addr, env->pc)); |
136 | break; | 134 | break; |
137 | } | 135 | } |
138 | return r; | 136 | return r; |
@@ -167,7 +165,7 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v) | @@ -167,7 +165,7 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v) | ||
167 | { | 165 | { |
168 | case 0: | 166 | case 0: |
169 | case 1: | 167 | case 1: |
170 | - printf ("extern or disabled timer clock?\n"); | 168 | + D(printf ("extern or disabled timer clock?\n")); |
171 | break; | 169 | break; |
172 | case 4: freq_hz = 29493000; break; | 170 | case 4: freq_hz = 29493000; break; |
173 | case 5: freq_hz = 32000000; break; | 171 | case 5: freq_hz = 32000000; break; |
@@ -178,7 +176,7 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v) | @@ -178,7 +176,7 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v) | ||
178 | break; | 176 | break; |
179 | } | 177 | } |
180 | 178 | ||
181 | - printf ("freq_hz=%d limit=%d\n", freq_hz, t->limit); | 179 | + D(printf ("freq_hz=%d limit=%d\n", freq_hz, t->limit)); |
182 | t->scale = 0; | 180 | t->scale = 0; |
183 | if (t->limit > 2048) | 181 | if (t->limit > 2048) |
184 | { | 182 | { |
@@ -186,11 +184,11 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v) | @@ -186,11 +184,11 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v) | ||
186 | ptimer_set_period(t->ptimer, freq_hz / t->scale); | 184 | ptimer_set_period(t->ptimer, freq_hz / t->scale); |
187 | } | 185 | } |
188 | 186 | ||
189 | - printf ("op=%d\n", op); | ||
190 | switch (op) | 187 | switch (op) |
191 | { | 188 | { |
192 | case 0: | 189 | case 0: |
193 | - printf ("limit=%d %d\n", t->limit, t->limit/t->scale); | 190 | + D(printf ("limit=%d %d\n", |
191 | + t->limit, t->limit/t->scale)); | ||
194 | ptimer_set_limit(t->ptimer, t->limit / t->scale, 1); | 192 | ptimer_set_limit(t->ptimer, t->limit / t->scale, 1); |
195 | break; | 193 | break; |
196 | case 1: | 194 | case 1: |
@@ -207,10 +205,8 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v) | @@ -207,10 +205,8 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v) | ||
207 | 205 | ||
208 | static void timer_ack_irq(struct fs_timer_t *t) | 206 | static void timer_ack_irq(struct fs_timer_t *t) |
209 | { | 207 | { |
210 | - if (!(r_intr & t->mask & rw_intr_mask)) { | 208 | + if (!(t->r_intr & t->mask & t->rw_intr_mask)) |
211 | qemu_irq_lower(t->irq[0]); | 209 | qemu_irq_lower(t->irq[0]); |
212 | - etrax_ack_irq(t->env, 1 << 0x1b); | ||
213 | - } | ||
214 | } | 210 | } |
215 | 211 | ||
216 | static void | 212 | static void |
@@ -239,10 +235,13 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | @@ -239,10 +235,13 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
239 | break; | 235 | break; |
240 | case RW_INTR_MASK: | 236 | case RW_INTR_MASK: |
241 | D(printf ("RW_INTR_MASK=%x\n", value)); | 237 | D(printf ("RW_INTR_MASK=%x\n", value)); |
242 | - rw_intr_mask = value; | 238 | + timer[t].rw_intr_mask = value; |
239 | + break; | ||
240 | + case RW_WD_CTRL: | ||
241 | + D(printf ("RW_WD_CTRL=%x\n", value)); | ||
243 | break; | 242 | break; |
244 | case RW_ACK_INTR: | 243 | case RW_ACK_INTR: |
245 | - r_intr &= ~value; | 244 | + timer[t].r_intr &= ~value; |
246 | timer_ack_irq(&timer[t]); | 245 | timer_ack_irq(&timer[t]); |
247 | break; | 246 | break; |
248 | default: | 247 | default: |
@@ -267,8 +266,9 @@ static CPUWriteMemoryFunc *timer_write[] = { | @@ -267,8 +266,9 @@ static CPUWriteMemoryFunc *timer_write[] = { | ||
267 | static void timer_irq(void *opaque) | 266 | static void timer_irq(void *opaque) |
268 | { | 267 | { |
269 | struct fs_timer_t *t = opaque; | 268 | struct fs_timer_t *t = opaque; |
270 | - r_intr |= t->mask; | ||
271 | - if (t->mask & rw_intr_mask) { | 269 | + t->r_intr |= t->mask; |
270 | + if (t->mask & t->rw_intr_mask) { | ||
271 | + D(printf("%s raise\n", __func__)); | ||
272 | qemu_irq_raise(t->irq[0]); | 272 | qemu_irq_raise(t->irq[0]); |
273 | } | 273 | } |
274 | } | 274 | } |
@@ -279,13 +279,13 @@ void etraxfs_timer_init(CPUState *env, qemu_irq *irqs) | @@ -279,13 +279,13 @@ void etraxfs_timer_init(CPUState *env, qemu_irq *irqs) | ||
279 | 279 | ||
280 | timer[0].bh = qemu_bh_new(timer_irq, &timer[0]); | 280 | timer[0].bh = qemu_bh_new(timer_irq, &timer[0]); |
281 | timer[0].ptimer = ptimer_init(timer[0].bh); | 281 | timer[0].ptimer = ptimer_init(timer[0].bh); |
282 | - timer[0].irq = irqs + 0x1b; | 282 | + timer[0].irq = irqs + 26; |
283 | timer[0].mask = 1; | 283 | timer[0].mask = 1; |
284 | timer[0].env = env; | 284 | timer[0].env = env; |
285 | 285 | ||
286 | timer[1].bh = qemu_bh_new(timer_irq, &timer[1]); | 286 | timer[1].bh = qemu_bh_new(timer_irq, &timer[1]); |
287 | timer[1].ptimer = ptimer_init(timer[1].bh); | 287 | timer[1].ptimer = ptimer_init(timer[1].bh); |
288 | - timer[1].irq = irqs + 0x1b; | 288 | + timer[1].irq = irqs + 26; |
289 | timer[1].mask = 1; | 289 | timer[1].mask = 1; |
290 | timer[1].env = env; | 290 | timer[1].env = env; |
291 | 291 |
target-cris/helper.c
@@ -28,6 +28,8 @@ | @@ -28,6 +28,8 @@ | ||
28 | #include "exec-all.h" | 28 | #include "exec-all.h" |
29 | #include "host-utils.h" | 29 | #include "host-utils.h" |
30 | 30 | ||
31 | +#define D(x) | ||
32 | + | ||
31 | #if defined(CONFIG_USER_ONLY) | 33 | #if defined(CONFIG_USER_ONLY) |
32 | 34 | ||
33 | void do_interrupt (CPUState *env) | 35 | void do_interrupt (CPUState *env) |
@@ -53,71 +55,68 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr) | @@ -53,71 +55,68 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr) | ||
53 | 55 | ||
54 | #else /* !CONFIG_USER_ONLY */ | 56 | #else /* !CONFIG_USER_ONLY */ |
55 | 57 | ||
58 | + | ||
59 | +static void cris_shift_ccs(CPUState *env) | ||
60 | +{ | ||
61 | + uint32_t ccs; | ||
62 | + /* Apply the ccs shift. */ | ||
63 | + ccs = env->pregs[PR_CCS]; | ||
64 | + ccs = (ccs & 0xc0000000) | ((ccs << 12) >> 2); | ||
65 | + env->pregs[PR_CCS] = ccs; | ||
66 | +} | ||
67 | + | ||
56 | int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | 68 | int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, |
57 | int mmu_idx, int is_softmmu) | 69 | int mmu_idx, int is_softmmu) |
58 | { | 70 | { |
59 | struct cris_mmu_result_t res; | 71 | struct cris_mmu_result_t res; |
60 | int prot, miss; | 72 | int prot, miss; |
73 | + int r = -1; | ||
61 | target_ulong phy; | 74 | target_ulong phy; |
62 | 75 | ||
76 | + D(printf ("%s addr=%x pc=%x\n", __func__, address, env->pc)); | ||
63 | address &= TARGET_PAGE_MASK; | 77 | address &= TARGET_PAGE_MASK; |
64 | prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; | 78 | prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; |
65 | miss = cris_mmu_translate(&res, env, address, rw, mmu_idx); | 79 | miss = cris_mmu_translate(&res, env, address, rw, mmu_idx); |
66 | if (miss) | 80 | if (miss) |
67 | { | 81 | { |
68 | - /* handle the miss. */ | ||
69 | - phy = 0; | ||
70 | - env->exception_index = EXCP_MMU_MISS; | 82 | + env->exception_index = EXCP_MMU_FAULT; |
83 | + env->fault_vector = res.bf_vec; | ||
84 | + r = 1; | ||
71 | } | 85 | } |
72 | else | 86 | else |
73 | { | 87 | { |
74 | phy = res.phy; | 88 | phy = res.phy; |
89 | + prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; | ||
90 | + r = tlb_set_page(env, address, phy, prot, mmu_idx, is_softmmu); | ||
75 | } | 91 | } |
76 | - return tlb_set_page(env, address, phy, prot, mmu_idx, is_softmmu); | ||
77 | -} | ||
78 | - | ||
79 | - | ||
80 | -static void cris_shift_ccs(CPUState *env) | ||
81 | -{ | ||
82 | - uint32_t ccs; | ||
83 | - /* Apply the ccs shift. */ | ||
84 | - ccs = env->pregs[PR_CCS]; | ||
85 | - ccs = (ccs & 0xc0000000) | ((ccs << 12) >> 2); | ||
86 | - env->pregs[PR_CCS] = ccs; | 92 | + D(printf("%s returns %d irqreq=%x addr=%x ismmu=%d\n", |
93 | + __func__, r, env->interrupt_request, | ||
94 | + address, is_softmmu)); | ||
95 | + return r; | ||
87 | } | 96 | } |
88 | 97 | ||
89 | void do_interrupt(CPUState *env) | 98 | void do_interrupt(CPUState *env) |
90 | { | 99 | { |
91 | - uint32_t ebp, isr; | ||
92 | - int irqnum; | ||
93 | - | ||
94 | - fflush(NULL); | 100 | + int ex_vec = -1; |
95 | 101 | ||
96 | -#if 0 | ||
97 | - printf ("exception index=%d interrupt_req=%d\n", | ||
98 | - env->exception_index, | ||
99 | - env->interrupt_request); | ||
100 | -#endif | 102 | + D(fprintf (stderr, "exception index=%d interrupt_req=%d\n", |
103 | + env->exception_index, | ||
104 | + env->interrupt_request)); | ||
101 | 105 | ||
102 | switch (env->exception_index) | 106 | switch (env->exception_index) |
103 | { | 107 | { |
104 | case EXCP_BREAK: | 108 | case EXCP_BREAK: |
105 | - irqnum = env->trapnr; | ||
106 | - ebp = env->pregs[PR_EBP]; | ||
107 | - isr = ldl_code(ebp + irqnum * 4); | 109 | + /* These exceptions are genereated by the core itself. |
110 | + ERP should point to the insn following the brk. */ | ||
111 | + ex_vec = env->trap_vector; | ||
108 | env->pregs[PR_ERP] = env->pc + 2; | 112 | env->pregs[PR_ERP] = env->pc + 2; |
109 | - env->pc = isr; | ||
110 | - | ||
111 | - cris_shift_ccs(env); | ||
112 | - | ||
113 | break; | 113 | break; |
114 | - case EXCP_MMU_MISS: | ||
115 | - irqnum = 4; | ||
116 | - ebp = env->pregs[PR_EBP]; | ||
117 | - isr = ldl_code(ebp + irqnum * 4); | ||
118 | - env->pregs[PR_ERP] = env->pc; | ||
119 | - env->pc = isr; | ||
120 | - cris_shift_ccs(env); | 114 | + |
115 | + case EXCP_MMU_FAULT: | ||
116 | + /* ERP is already setup by translate-all.c through | ||
117 | + re-translation of the aborted TB combined with | ||
118 | + pc searching. */ | ||
119 | + ex_vec = env->fault_vector; | ||
121 | break; | 120 | break; |
122 | 121 | ||
123 | default: | 122 | default: |
@@ -125,34 +124,29 @@ void do_interrupt(CPUState *env) | @@ -125,34 +124,29 @@ void do_interrupt(CPUState *env) | ||
125 | /* Maybe the irq was acked by sw before we got a | 124 | /* Maybe the irq was acked by sw before we got a |
126 | change to take it. */ | 125 | change to take it. */ |
127 | if (env->interrupt_request & CPU_INTERRUPT_HARD) { | 126 | if (env->interrupt_request & CPU_INTERRUPT_HARD) { |
128 | - if (!env->pending_interrupts) | 127 | + /* Vectors below 0x30 are internal |
128 | + exceptions, i.e not interrupt requests | ||
129 | + from the interrupt controller. */ | ||
130 | + if (env->interrupt_vector < 0x30) | ||
129 | return; | 131 | return; |
132 | + /* Is the core accepting interrupts? */ | ||
130 | if (!(env->pregs[PR_CCS] & I_FLAG)) { | 133 | if (!(env->pregs[PR_CCS] & I_FLAG)) { |
131 | return; | 134 | return; |
132 | } | 135 | } |
133 | - | ||
134 | - irqnum = 31 - clz32(env->pending_interrupts); | ||
135 | - irqnum += 0x30; | ||
136 | - ebp = env->pregs[PR_EBP]; | ||
137 | - isr = ldl_code(ebp + irqnum * 4); | 136 | + /* The interrupt controller gives us the |
137 | + vector. */ | ||
138 | + ex_vec = env->interrupt_vector; | ||
139 | + /* Normal interrupts are taken between | ||
140 | + TB's. env->pc is valid here. */ | ||
138 | env->pregs[PR_ERP] = env->pc; | 141 | env->pregs[PR_ERP] = env->pc; |
139 | - env->pc = isr; | ||
140 | - | ||
141 | - cris_shift_ccs(env); | ||
142 | -#if 0 | ||
143 | - printf ("%s ebp=%x %x isr=%x %d" | ||
144 | - " ir=%x pending=%x\n", | ||
145 | - __func__, | ||
146 | - ebp, ebp + irqnum * 4, | ||
147 | - isr, env->exception_index, | ||
148 | - env->interrupt_request, | ||
149 | - env->pending_interrupts); | ||
150 | -#endif | ||
151 | } | 142 | } |
152 | - | ||
153 | } | 143 | } |
154 | break; | 144 | break; |
155 | } | 145 | } |
146 | + env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4); | ||
147 | + /* Apply the CRIS CCS shift. */ | ||
148 | + cris_shift_ccs(env); | ||
149 | + D(printf ("%s ebp=%x isr=%x vec=%x\n", __func__, ebp, isr, ex_vec)); | ||
156 | } | 150 | } |
157 | 151 | ||
158 | target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr) | 152 | target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr) |
@@ -163,6 +157,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr) | @@ -163,6 +157,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr) | ||
163 | miss = cris_mmu_translate(&res, env, addr, 0, 0); | 157 | miss = cris_mmu_translate(&res, env, addr, 0, 0); |
164 | if (!miss) | 158 | if (!miss) |
165 | phy = res.phy; | 159 | phy = res.phy; |
160 | + D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy)); | ||
166 | return phy; | 161 | return phy; |
167 | } | 162 | } |
168 | #endif | 163 | #endif |
translate-all.c
@@ -286,6 +286,8 @@ int cpu_restore_state(TranslationBlock *tb, | @@ -286,6 +286,8 @@ int cpu_restore_state(TranslationBlock *tb, | ||
286 | #elif defined(TARGET_SH4) | 286 | #elif defined(TARGET_SH4) |
287 | env->pc = gen_opc_pc[j]; | 287 | env->pc = gen_opc_pc[j]; |
288 | env->flags = gen_opc_hflags[j]; | 288 | env->flags = gen_opc_hflags[j]; |
289 | +#elif defined(TARGET_CRIS) | ||
290 | + env->pregs[PR_ERP] = gen_opc_pc[j]; | ||
289 | #endif | 291 | #endif |
290 | 292 | ||
291 | #ifdef CONFIG_PROFILER | 293 | #ifdef CONFIG_PROFILER |