Commit 1640695026373034f9740ad1bcb69f27e584218c
1 parent
008a8818
Add nominal ARM Versatil/AB board emulation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1864 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
153 additions
and
173 deletions
Makefile.target
| ... | ... | @@ -346,7 +346,7 @@ endif |
| 346 | 346 | endif |
| 347 | 347 | ifeq ($(TARGET_BASE_ARCH), arm) |
| 348 | 348 | VL_OBJS+= integratorcp.o versatilepb.o ps2.o smc91c111.o arm_pic.o arm_timer.o |
| 349 | -VL_OBJS+= pl011.o pl050.o pl080.o pl110.o pl190.o | |
| 349 | +VL_OBJS+= arm_boot.o pl011.o pl050.o pl080.o pl110.o pl190.o | |
| 350 | 350 | endif |
| 351 | 351 | ifeq ($(TARGET_BASE_ARCH), sh4) |
| 352 | 352 | VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o | ... | ... |
hw/arm_boot.c
0 → 100644
| 1 | +/* | |
| 2 | + * ARM kernel loader. | |
| 3 | + * | |
| 4 | + * Copyright (c) 2006 CodeSourcery. | |
| 5 | + * Written by Paul Brook | |
| 6 | + * | |
| 7 | + * This code is licenced under the GPL. | |
| 8 | + */ | |
| 9 | + | |
| 10 | +#include "vl.h" | |
| 11 | + | |
| 12 | +#define KERNEL_ARGS_ADDR 0x100 | |
| 13 | +#define KERNEL_LOAD_ADDR 0x00010000 | |
| 14 | +#define INITRD_LOAD_ADDR 0x00800000 | |
| 15 | + | |
| 16 | +/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */ | |
| 17 | +static uint32_t bootloader[] = { | |
| 18 | + 0xe3a00000, /* mov r0, #0 */ | |
| 19 | + 0xe3a01000, /* mov r1, #0x?? */ | |
| 20 | + 0xe3811c00, /* orr r1, r1, #0x??00 */ | |
| 21 | + 0xe59f2000, /* ldr r2, [pc, #0] */ | |
| 22 | + 0xe59ff000, /* ldr pc, [pc, #0] */ | |
| 23 | + 0, /* Address of kernel args. Set by integratorcp_init. */ | |
| 24 | + 0 /* Kernel entry point. Set by integratorcp_init. */ | |
| 25 | +}; | |
| 26 | + | |
| 27 | +static void set_kernel_args(uint32_t ram_size, int initrd_size, | |
| 28 | + const char *kernel_cmdline) | |
| 29 | +{ | |
| 30 | + uint32_t *p; | |
| 31 | + | |
| 32 | + p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR); | |
| 33 | + /* ATAG_CORE */ | |
| 34 | + stl_raw(p++, 5); | |
| 35 | + stl_raw(p++, 0x54410001); | |
| 36 | + stl_raw(p++, 1); | |
| 37 | + stl_raw(p++, 0x1000); | |
| 38 | + stl_raw(p++, 0); | |
| 39 | + /* ATAG_MEM */ | |
| 40 | + stl_raw(p++, 4); | |
| 41 | + stl_raw(p++, 0x54410002); | |
| 42 | + stl_raw(p++, ram_size); | |
| 43 | + stl_raw(p++, 0); | |
| 44 | + if (initrd_size) { | |
| 45 | + /* ATAG_INITRD2 */ | |
| 46 | + stl_raw(p++, 4); | |
| 47 | + stl_raw(p++, 0x54420005); | |
| 48 | + stl_raw(p++, INITRD_LOAD_ADDR); | |
| 49 | + stl_raw(p++, initrd_size); | |
| 50 | + } | |
| 51 | + if (kernel_cmdline && *kernel_cmdline) { | |
| 52 | + /* ATAG_CMDLINE */ | |
| 53 | + int cmdline_size; | |
| 54 | + | |
| 55 | + cmdline_size = strlen(kernel_cmdline); | |
| 56 | + memcpy (p + 2, kernel_cmdline, cmdline_size + 1); | |
| 57 | + cmdline_size = (cmdline_size >> 2) + 1; | |
| 58 | + stl_raw(p++, cmdline_size + 2); | |
| 59 | + stl_raw(p++, 0x54410009); | |
| 60 | + p += cmdline_size; | |
| 61 | + } | |
| 62 | + /* ATAG_END */ | |
| 63 | + stl_raw(p++, 0); | |
| 64 | + stl_raw(p++, 0); | |
| 65 | +} | |
| 66 | + | |
| 67 | +void arm_load_kernel(int ram_size, const char *kernel_filename, | |
| 68 | + const char *kernel_cmdline, const char *initrd_filename, | |
| 69 | + int board_id) | |
| 70 | +{ | |
| 71 | + int kernel_size; | |
| 72 | + int initrd_size; | |
| 73 | + int n; | |
| 74 | + | |
| 75 | + /* Load the kernel. */ | |
| 76 | + if (!kernel_filename) { | |
| 77 | + fprintf(stderr, "Kernel image must be specified\n"); | |
| 78 | + exit(1); | |
| 79 | + } | |
| 80 | + kernel_size = load_image(kernel_filename, | |
| 81 | + phys_ram_base + KERNEL_LOAD_ADDR); | |
| 82 | + if (kernel_size < 0) { | |
| 83 | + fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename); | |
| 84 | + exit(1); | |
| 85 | + } | |
| 86 | + if (initrd_filename) { | |
| 87 | + initrd_size = load_image(initrd_filename, | |
| 88 | + phys_ram_base + INITRD_LOAD_ADDR); | |
| 89 | + if (initrd_size < 0) { | |
| 90 | + fprintf(stderr, "qemu: could not load initrd '%s'\n", | |
| 91 | + initrd_filename); | |
| 92 | + exit(1); | |
| 93 | + } | |
| 94 | + } else { | |
| 95 | + initrd_size = 0; | |
| 96 | + } | |
| 97 | + bootloader[1] |= board_id & 0xff; | |
| 98 | + bootloader[2] |= (board_id >> 8) & 0xff; | |
| 99 | + bootloader[5] = KERNEL_ARGS_ADDR; | |
| 100 | + bootloader[6] = KERNEL_LOAD_ADDR; | |
| 101 | + for (n = 0; n < sizeof(bootloader) / 4; n++) | |
| 102 | + stl_raw(phys_ram_base + (n * 4), bootloader[n]); | |
| 103 | + set_kernel_args(ram_size, initrd_size, kernel_cmdline); | |
| 104 | +} | |
| 105 | + | ... | ... |
hw/integratorcp.c
| ... | ... | @@ -10,10 +10,6 @@ |
| 10 | 10 | #include "vl.h" |
| 11 | 11 | #include "arm_pic.h" |
| 12 | 12 | |
| 13 | -#define KERNEL_ARGS_ADDR 0x100 | |
| 14 | -#define KERNEL_LOAD_ADDR 0x00010000 | |
| 15 | -#define INITRD_LOAD_ADDR 0x00800000 | |
| 16 | - | |
| 17 | 13 | void DMA_run (void) |
| 18 | 14 | { |
| 19 | 15 | } |
| ... | ... | @@ -470,57 +466,6 @@ static void icp_control_init(uint32_t base) |
| 470 | 466 | } |
| 471 | 467 | |
| 472 | 468 | |
| 473 | -/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */ | |
| 474 | -static uint32_t bootloader[] = { | |
| 475 | - 0xe3a00000, /* mov r0, #0 */ | |
| 476 | - 0xe3a01013, /* mov r1, #0x13 */ | |
| 477 | - 0xe3811c01, /* orr r1, r1, #0x100 */ | |
| 478 | - 0xe59f2000, /* ldr r2, [pc, #0] */ | |
| 479 | - 0xe59ff000, /* ldr pc, [pc, #0] */ | |
| 480 | - 0, /* Address of kernel args. Set by integratorcp_init. */ | |
| 481 | - 0 /* Kernel entry point. Set by integratorcp_init. */ | |
| 482 | -}; | |
| 483 | - | |
| 484 | -static void set_kernel_args(uint32_t ram_size, int initrd_size, | |
| 485 | - const char *kernel_cmdline) | |
| 486 | -{ | |
| 487 | - uint32_t *p; | |
| 488 | - | |
| 489 | - p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR); | |
| 490 | - /* ATAG_CORE */ | |
| 491 | - stl_raw(p++, 5); | |
| 492 | - stl_raw(p++, 0x54410001); | |
| 493 | - stl_raw(p++, 1); | |
| 494 | - stl_raw(p++, 0x1000); | |
| 495 | - stl_raw(p++, 0); | |
| 496 | - /* ATAG_MEM */ | |
| 497 | - stl_raw(p++, 4); | |
| 498 | - stl_raw(p++, 0x54410002); | |
| 499 | - stl_raw(p++, ram_size); | |
| 500 | - stl_raw(p++, 0); | |
| 501 | - if (initrd_size) { | |
| 502 | - /* ATAG_INITRD2 */ | |
| 503 | - stl_raw(p++, 4); | |
| 504 | - stl_raw(p++, 0x54420005); | |
| 505 | - stl_raw(p++, INITRD_LOAD_ADDR); | |
| 506 | - stl_raw(p++, initrd_size); | |
| 507 | - } | |
| 508 | - if (kernel_cmdline && *kernel_cmdline) { | |
| 509 | - /* ATAG_CMDLINE */ | |
| 510 | - int cmdline_size; | |
| 511 | - | |
| 512 | - cmdline_size = strlen(kernel_cmdline); | |
| 513 | - memcpy (p + 2, kernel_cmdline, cmdline_size + 1); | |
| 514 | - cmdline_size = (cmdline_size >> 2) + 1; | |
| 515 | - stl_raw(p++, cmdline_size + 2); | |
| 516 | - stl_raw(p++, 0x54410009); | |
| 517 | - p += cmdline_size; | |
| 518 | - } | |
| 519 | - /* ATAG_END */ | |
| 520 | - stl_raw(p++, 0); | |
| 521 | - stl_raw(p++, 0); | |
| 522 | -} | |
| 523 | - | |
| 524 | 469 | /* Board init. */ |
| 525 | 470 | |
| 526 | 471 | static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device, |
| ... | ... | @@ -532,9 +477,6 @@ static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device, |
| 532 | 477 | uint32_t bios_offset; |
| 533 | 478 | icp_pic_state *pic; |
| 534 | 479 | void *cpu_pic; |
| 535 | - int kernel_size; | |
| 536 | - int initrd_size; | |
| 537 | - int n; | |
| 538 | 480 | |
| 539 | 481 | env = cpu_init(); |
| 540 | 482 | cpu_arm_set_model(env, cpuid); |
| ... | ... | @@ -567,33 +509,8 @@ static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device, |
| 567 | 509 | } |
| 568 | 510 | pl110_init(ds, 0xc0000000, pic, 22, 0); |
| 569 | 511 | |
| 570 | - /* Load the kernel. */ | |
| 571 | - if (!kernel_filename) { | |
| 572 | - fprintf(stderr, "Kernel image must be specified\n"); | |
| 573 | - exit(1); | |
| 574 | - } | |
| 575 | - kernel_size = load_image(kernel_filename, | |
| 576 | - phys_ram_base + KERNEL_LOAD_ADDR); | |
| 577 | - if (kernel_size < 0) { | |
| 578 | - fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename); | |
| 579 | - exit(1); | |
| 580 | - } | |
| 581 | - if (initrd_filename) { | |
| 582 | - initrd_size = load_image(initrd_filename, | |
| 583 | - phys_ram_base + INITRD_LOAD_ADDR); | |
| 584 | - if (initrd_size < 0) { | |
| 585 | - fprintf(stderr, "qemu: could not load initrd '%s'\n", | |
| 586 | - initrd_filename); | |
| 587 | - exit(1); | |
| 588 | - } | |
| 589 | - } else { | |
| 590 | - initrd_size = 0; | |
| 591 | - } | |
| 592 | - bootloader[5] = KERNEL_ARGS_ADDR; | |
| 593 | - bootloader[6] = KERNEL_LOAD_ADDR; | |
| 594 | - for (n = 0; n < sizeof(bootloader) / 4; n++) | |
| 595 | - stl_raw(phys_ram_base + (n * 4), bootloader[n]); | |
| 596 | - set_kernel_args(ram_size, initrd_size, kernel_cmdline); | |
| 512 | + arm_load_kernel(ram_size, kernel_filename, kernel_cmdline, | |
| 513 | + initrd_filename, 0x113); | |
| 597 | 514 | } |
| 598 | 515 | |
| 599 | 516 | static void integratorcp926_init(int ram_size, int vga_ram_size, | ... | ... |
hw/versatilepb.c
| 1 | 1 | /* |
| 2 | - * ARM Versatile Platform Baseboard System emulation. | |
| 2 | + * ARM Versatile Platform/Application Baseboard System emulation. | |
| 3 | 3 | * |
| 4 | 4 | * Copyright (c) 2005-2006 CodeSourcery. |
| 5 | 5 | * Written by Paul Brook |
| ... | ... | @@ -10,10 +10,6 @@ |
| 10 | 10 | #include "vl.h" |
| 11 | 11 | #include "arm_pic.h" |
| 12 | 12 | |
| 13 | -#define KERNEL_ARGS_ADDR 0x100 | |
| 14 | -#define KERNEL_LOAD_ADDR 0x00010000 | |
| 15 | -#define INITRD_LOAD_ADDR 0x00800000 | |
| 16 | - | |
| 17 | 13 | /* Primary interrupt controller. */ |
| 18 | 14 | |
| 19 | 15 | typedef struct vpb_sic_state |
| ... | ... | @@ -151,66 +147,16 @@ static vpb_sic_state *vpb_sic_init(uint32_t base, void *parent, int irq) |
| 151 | 147 | |
| 152 | 148 | /* Board init. */ |
| 153 | 149 | |
| 154 | -/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */ | |
| 155 | -static uint32_t bootloader[] = { | |
| 156 | - 0xe3a00000, /* mov r0, #0 */ | |
| 157 | - 0xe3a01083, /* mov r1, #0x83 */ | |
| 158 | - 0xe3811c01, /* orr r1, r1, #0x100 */ | |
| 159 | - 0xe59f2000, /* ldr r2, [pc, #0] */ | |
| 160 | - 0xe59ff000, /* ldr pc, [pc, #0] */ | |
| 161 | - 0, /* Address of kernel args. Set by integratorcp_init. */ | |
| 162 | - 0 /* Kernel entry point. Set by integratorcp_init. */ | |
| 163 | -}; | |
| 164 | - | |
| 165 | -static void set_kernel_args(uint32_t ram_size, int initrd_size, | |
| 166 | - const char *kernel_cmdline) | |
| 167 | -{ | |
| 168 | - uint32_t *p; | |
| 169 | - | |
| 170 | - p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR); | |
| 171 | - /* ATAG_CORE */ | |
| 172 | - stl_raw(p++, 5); | |
| 173 | - stl_raw(p++, 0x54410001); | |
| 174 | - stl_raw(p++, 1); | |
| 175 | - stl_raw(p++, 0x1000); | |
| 176 | - stl_raw(p++, 0); | |
| 177 | - /* ATAG_MEM */ | |
| 178 | - stl_raw(p++, 4); | |
| 179 | - stl_raw(p++, 0x54410002); | |
| 180 | - stl_raw(p++, ram_size); | |
| 181 | - stl_raw(p++, 0); | |
| 182 | - if (initrd_size) { | |
| 183 | - /* ATAG_INITRD2 */ | |
| 184 | - stl_raw(p++, 4); | |
| 185 | - stl_raw(p++, 0x54420005); | |
| 186 | - stl_raw(p++, INITRD_LOAD_ADDR); | |
| 187 | - stl_raw(p++, initrd_size); | |
| 188 | - } | |
| 189 | - if (kernel_cmdline && *kernel_cmdline) { | |
| 190 | - /* ATAG_CMDLINE */ | |
| 191 | - int cmdline_size; | |
| 150 | +/* The AB and PB boards both use the same core, just with different | |
| 151 | + peripherans and expansion busses. For now we emulate a subset of the | |
| 152 | + PB peripherals and just change the board ID. */ | |
| 192 | 153 | |
| 193 | - cmdline_size = strlen(kernel_cmdline); | |
| 194 | - memcpy (p + 2, kernel_cmdline, cmdline_size + 1); | |
| 195 | - cmdline_size = (cmdline_size >> 2) + 1; | |
| 196 | - stl_raw(p++, cmdline_size + 2); | |
| 197 | - stl_raw(p++, 0x54410009); | |
| 198 | - p += cmdline_size; | |
| 199 | - } | |
| 200 | - /* ATAG_END */ | |
| 201 | - stl_raw(p++, 0); | |
| 202 | - stl_raw(p++, 0); | |
| 203 | -} | |
| 204 | - | |
| 205 | -static void vpb_init(int ram_size, int vga_ram_size, int boot_device, | |
| 154 | +static void versatile_init(int ram_size, int vga_ram_size, int boot_device, | |
| 206 | 155 | DisplayState *ds, const char **fd_filename, int snapshot, |
| 207 | 156 | const char *kernel_filename, const char *kernel_cmdline, |
| 208 | - const char *initrd_filename) | |
| 157 | + const char *initrd_filename, int board_id) | |
| 209 | 158 | { |
| 210 | 159 | CPUState *env; |
| 211 | - int kernel_size; | |
| 212 | - int initrd_size; | |
| 213 | - int n; | |
| 214 | 160 | void *pic; |
| 215 | 161 | void *sic; |
| 216 | 162 | |
| ... | ... | @@ -250,6 +196,7 @@ static void vpb_init(int ram_size, int vga_ram_size, int boot_device, |
| 250 | 196 | that includes hardware cursor support from the PL111. */ |
| 251 | 197 | pl110_init(ds, 0x10120000, pic, 16, 1); |
| 252 | 198 | |
| 199 | + /* Memory map for Versatile/PB: */ | |
| 253 | 200 | /* 0x10000000 System registers. */ |
| 254 | 201 | /* 0x10001000 PCI controller config registers. */ |
| 255 | 202 | /* 0x10002000 Serial bus interface. */ |
| ... | ... | @@ -285,33 +232,30 @@ static void vpb_init(int ram_size, int vga_ram_size, int boot_device, |
| 285 | 232 | /* 0x101f3000 UART2. */ |
| 286 | 233 | /* 0x101f4000 SSPI. */ |
| 287 | 234 | |
| 288 | - /* Load the kernel. */ | |
| 289 | - if (!kernel_filename) { | |
| 290 | - fprintf(stderr, "Kernel image must be specified\n"); | |
| 291 | - exit(1); | |
| 292 | - } | |
| 293 | - kernel_size = load_image(kernel_filename, | |
| 294 | - phys_ram_base + KERNEL_LOAD_ADDR); | |
| 295 | - if (kernel_size < 0) { | |
| 296 | - fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename); | |
| 297 | - exit(1); | |
| 298 | - } | |
| 299 | - if (initrd_filename) { | |
| 300 | - initrd_size = load_image(initrd_filename, | |
| 301 | - phys_ram_base + INITRD_LOAD_ADDR); | |
| 302 | - if (initrd_size < 0) { | |
| 303 | - fprintf(stderr, "qemu: could not load initrd '%s'\n", | |
| 304 | - initrd_filename); | |
| 305 | - exit(1); | |
| 306 | - } | |
| 307 | - } else { | |
| 308 | - initrd_size = 0; | |
| 309 | - } | |
| 310 | - bootloader[5] = KERNEL_ARGS_ADDR; | |
| 311 | - bootloader[6] = KERNEL_LOAD_ADDR; | |
| 312 | - for (n = 0; n < sizeof(bootloader) / 4; n++) | |
| 313 | - stl_raw(phys_ram_base + (n * 4), bootloader[n]); | |
| 314 | - set_kernel_args(ram_size, initrd_size, kernel_cmdline); | |
| 235 | + arm_load_kernel(ram_size, kernel_filename, kernel_cmdline, | |
| 236 | + initrd_filename, board_id); | |
| 237 | +} | |
| 238 | + | |
| 239 | +static void vpb_init(int ram_size, int vga_ram_size, int boot_device, | |
| 240 | + DisplayState *ds, const char **fd_filename, int snapshot, | |
| 241 | + const char *kernel_filename, const char *kernel_cmdline, | |
| 242 | + const char *initrd_filename) | |
| 243 | +{ | |
| 244 | + versatile_init(ram_size, vga_ram_size, boot_device, | |
| 245 | + ds, fd_filename, snapshot, | |
| 246 | + kernel_filename, kernel_cmdline, | |
| 247 | + initrd_filename, 0x183); | |
| 248 | +} | |
| 249 | + | |
| 250 | +static void vab_init(int ram_size, int vga_ram_size, int boot_device, | |
| 251 | + DisplayState *ds, const char **fd_filename, int snapshot, | |
| 252 | + const char *kernel_filename, const char *kernel_cmdline, | |
| 253 | + const char *initrd_filename) | |
| 254 | +{ | |
| 255 | + versatile_init(ram_size, vga_ram_size, boot_device, | |
| 256 | + ds, fd_filename, snapshot, | |
| 257 | + kernel_filename, kernel_cmdline, | |
| 258 | + initrd_filename, 0x25e); | |
| 315 | 259 | } |
| 316 | 260 | |
| 317 | 261 | QEMUMachine versatilepb_machine = { |
| ... | ... | @@ -319,3 +263,9 @@ QEMUMachine versatilepb_machine = { |
| 319 | 263 | "ARM Versatile/PB (ARM926EJ-S)", |
| 320 | 264 | vpb_init, |
| 321 | 265 | }; |
| 266 | + | |
| 267 | +QEMUMachine versatileab_machine = { | |
| 268 | + "versatileab", | |
| 269 | + "ARM Versatile/AB (ARM926EJ-S)", | |
| 270 | + vab_init, | |
| 271 | +}; | ... | ... |
vl.c
| ... | ... | @@ -4863,6 +4863,7 @@ void register_machines(void) |
| 4863 | 4863 | qemu_register_machine(&integratorcp926_machine); |
| 4864 | 4864 | qemu_register_machine(&integratorcp1026_machine); |
| 4865 | 4865 | qemu_register_machine(&versatilepb_machine); |
| 4866 | + qemu_register_machine(&versatileab_machine); | |
| 4866 | 4867 | #elif defined(TARGET_SH4) |
| 4867 | 4868 | qemu_register_machine(&shix_machine); |
| 4868 | 4869 | #else | ... | ... |
vl.h
| ... | ... | @@ -987,6 +987,7 @@ extern QEMUMachine integratorcp1026_machine; |
| 987 | 987 | |
| 988 | 988 | /* versatilepb.c */ |
| 989 | 989 | extern QEMUMachine versatilepb_machine; |
| 990 | +extern QEMUMachine versatileab_machine; | |
| 990 | 991 | |
| 991 | 992 | /* ps2.c */ |
| 992 | 993 | void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg); |
| ... | ... | @@ -1019,6 +1020,12 @@ void *pl190_init(uint32_t base, void *parent, int irq, int fiq); |
| 1019 | 1020 | void sp804_init(uint32_t base, void *pic, int irq); |
| 1020 | 1021 | void icp_pit_init(uint32_t base, void *pic, int irq); |
| 1021 | 1022 | |
| 1023 | +/* arm_boot.c */ | |
| 1024 | + | |
| 1025 | +void arm_load_kernel(int ram_size, const char *kernel_filename, | |
| 1026 | + const char *kernel_cmdline, const char *initrd_filename, | |
| 1027 | + int board_id); | |
| 1028 | + | |
| 1022 | 1029 | /* sh7750.c */ |
| 1023 | 1030 | struct SH7750State; |
| 1024 | 1031 | ... | ... |