Revision 983fe826
b/hw/armv7m.c | ||
---|---|---|
151 | 151 |
} |
152 | 152 |
|
153 | 153 |
/* Board init. */ |
154 |
|
|
155 |
static void armv7m_reset(void *opaque) |
|
156 |
{ |
|
157 |
cpu_reset((CPUState *)opaque); |
|
158 |
} |
|
159 |
|
|
154 | 160 |
/* Init CPU and memory for a v7-M based board. |
155 | 161 |
flash_size and sram_size are in kb. |
156 | 162 |
Returns the NVIC array. */ |
... | ... | |
163 | 169 |
/* FIXME: make this local state. */ |
164 | 170 |
static qemu_irq pic[64]; |
165 | 171 |
qemu_irq *cpu_pic; |
166 |
uint32_t pc; |
|
167 | 172 |
int image_size; |
168 | 173 |
uint64_t entry; |
169 | 174 |
uint64_t lowaddr; |
... | ... | |
201 | 206 |
armv7m_bitband_init(); |
202 | 207 |
|
203 | 208 |
nvic = qdev_create(NULL, "armv7m_nvic"); |
204 |
env->v7m.nvic = nvic;
|
|
209 |
env->nvic = nvic; |
|
205 | 210 |
qdev_init_nofail(nvic); |
206 | 211 |
cpu_pic = arm_pic_init_cpu(env); |
207 | 212 |
sysbus_connect_irq(sysbus_from_qdev(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]); |
... | ... | |
227 | 232 |
exit(1); |
228 | 233 |
} |
229 | 234 |
|
230 |
/* If the image was loaded at address zero then assume it is a |
|
231 |
regular ROM image and perform the normal CPU reset sequence. |
|
232 |
Otherwise jump directly to the entry point. */ |
|
233 |
if (lowaddr == 0) { |
|
234 |
env->regs[13] = ldl_phys(0); |
|
235 |
pc = ldl_phys(4); |
|
236 |
} else { |
|
237 |
pc = entry; |
|
238 |
} |
|
239 |
env->thumb = pc & 1; |
|
240 |
env->regs[15] = pc & ~1; |
|
241 |
|
|
242 | 235 |
/* Hack to map an additional page of ram at the top of the address |
243 | 236 |
space. This stops qemu complaining about executing code outside RAM |
244 | 237 |
when returning from an exception. */ |
245 | 238 |
cpu_register_physical_memory(0xfffff000, 0x1000, |
246 | 239 |
qemu_ram_alloc(0x1000) | IO_MEM_RAM); |
247 | 240 |
|
241 |
qemu_register_reset(armv7m_reset, env); |
|
248 | 242 |
return pic; |
249 | 243 |
} |
250 | 244 |
|
b/target-arm/cpu.h | ||
---|---|---|
146 | 146 |
int current_sp; |
147 | 147 |
int exception; |
148 | 148 |
int pending_exception; |
149 |
void *nvic; |
|
150 | 149 |
} v7m; |
151 | 150 |
|
152 | 151 |
/* Coprocessor IO used by peripherals */ |
... | ... | |
205 | 204 |
CPU_COMMON |
206 | 205 |
|
207 | 206 |
/* These fields after the common ones so they are preserved on reset. */ |
207 |
void *nvic; |
|
208 | 208 |
struct arm_boot_info *boot_info; |
209 | 209 |
} CPUARMState; |
210 | 210 |
|
b/target-arm/helper.c | ||
---|---|---|
8 | 8 |
#include "helpers.h" |
9 | 9 |
#include "qemu-common.h" |
10 | 10 |
#include "host-utils.h" |
11 |
#include "hw/loader.h" |
|
11 | 12 |
|
12 | 13 |
static uint32_t cortexa9_cp15_c0_c1[8] = |
13 | 14 |
{ 0x1031, 0x11, 0x000, 0, 0x00100103, 0x20000000, 0x01230000, 0x00002111 }; |
... | ... | |
204 | 205 |
#else |
205 | 206 |
/* SVC mode with interrupts disabled. */ |
206 | 207 |
env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I; |
208 |
env->regs[15] = 0; |
|
207 | 209 |
/* On ARMv7-M the CPSR_I is the value of the PRIMASK register, and is |
208 |
clear at reset. */ |
|
209 |
if (IS_M(env)) |
|
210 |
clear at reset. Initial SP and PC are loaded from ROM. */ |
|
211 |
if (IS_M(env)) { |
|
212 |
uint32_t pc; |
|
213 |
uint8_t *rom; |
|
210 | 214 |
env->uncached_cpsr &= ~CPSR_I; |
215 |
rom = rom_ptr(0); |
|
216 |
if (rom) { |
|
217 |
/* We should really use ldl_phys here, in case the guest |
|
218 |
modified flash and reset itself. However images |
|
219 |
loaded via -kenrel have not been copied yet, so load the |
|
220 |
values directly from there. */ |
|
221 |
env->regs[13] = ldl_p(rom); |
|
222 |
pc = ldl_p(rom + 4); |
|
223 |
env->thumb = pc & 1; |
|
224 |
env->regs[15] = pc & ~1; |
|
225 |
} |
|
226 |
} |
|
211 | 227 |
env->vfp.xregs[ARM_VFP_FPEXC] = 0; |
212 | 228 |
env->cp15.c2_base_mask = 0xffffc000u; |
213 | 229 |
#endif |
214 |
env->regs[15] = 0; |
|
215 | 230 |
tlb_flush(env, 1); |
216 | 231 |
} |
217 | 232 |
|
... | ... | |
624 | 639 |
|
625 | 640 |
type = env->regs[15]; |
626 | 641 |
if (env->v7m.exception != 0) |
627 |
armv7m_nvic_complete_irq(env->v7m.nvic, env->v7m.exception);
|
|
642 |
armv7m_nvic_complete_irq(env->nvic, env->v7m.exception); |
|
628 | 643 |
|
629 | 644 |
/* Switch to the target stack. */ |
630 | 645 |
switch_v7m_sp(env, (type & 4) != 0); |
... | ... | |
666 | 681 |
one we're raising. */ |
667 | 682 |
switch (env->exception_index) { |
668 | 683 |
case EXCP_UDEF: |
669 |
armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_USAGE);
|
|
684 |
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE); |
|
670 | 685 |
return; |
671 | 686 |
case EXCP_SWI: |
672 | 687 |
env->regs[15] += 2; |
673 |
armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_SVC);
|
|
688 |
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC); |
|
674 | 689 |
return; |
675 | 690 |
case EXCP_PREFETCH_ABORT: |
676 | 691 |
case EXCP_DATA_ABORT: |
677 |
armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_MEM);
|
|
692 |
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM); |
|
678 | 693 |
return; |
679 | 694 |
case EXCP_BKPT: |
680 | 695 |
if (semihosting_enabled) { |
... | ... | |
686 | 701 |
return; |
687 | 702 |
} |
688 | 703 |
} |
689 |
armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_DEBUG);
|
|
704 |
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG); |
|
690 | 705 |
return; |
691 | 706 |
case EXCP_IRQ: |
692 |
env->v7m.exception = armv7m_nvic_acknowledge_irq(env->v7m.nvic);
|
|
707 |
env->v7m.exception = armv7m_nvic_acknowledge_irq(env->nvic); |
|
693 | 708 |
break; |
694 | 709 |
case EXCP_EXCEPTION_EXIT: |
695 | 710 |
do_v7m_exception_exit(env); |
Also available in: Unified diff