8297be80f7
Convert all the multi-line uses of fprintf(stderr, "warning:"..."\n"... to use warn_report() instead. This helps standardise on a single method of printing warnings to the user. All of the warnings were changed using these commands: find ./* -type f -exec sed -i \ 'N; {s|fprintf(.*".*warning[,:] \(.*\)\\n"\(.*\));|warn_report("\1"\2);|Ig}' \ {} + find ./* -type f -exec sed -i \ 'N;N; {s|fprintf(.*".*warning[,:] \(.*\)\\n"\(.*\));|warn_report("\1"\2);|Ig}' \ {} + find ./* -type f -exec sed -i \ 'N;N;N; {s|fprintf(.*".*warning[,:] \(.*\)\\n"\(.*\));|warn_report("\1"\2);|Ig}' \ {} + find ./* -type f -exec sed -i \ 'N;N;N;N {s|fprintf(.*".*warning[,:] \(.*\)\\n"\(.*\));|warn_report("\1"\2);|Ig}' \ {} + find ./* -type f -exec sed -i \ 'N;N;N;N;N {s|fprintf(.*".*warning[,:] \(.*\)\\n"\(.*\));|warn_report("\1"\2);|Ig}' \ {} + find ./* -type f -exec sed -i \ 'N;N;N;N;N;N {s|fprintf(.*".*warning[,:] \(.*\)\\n"\(.*\));|warn_report("\1"\2);|Ig}' \ {} + find ./* -type f -exec sed -i \ 'N;N;N;N;N;N;N; {s|fprintf(.*".*warning[,:] \(.*\)\\n"\(.*\));|warn_report("\1"\2);|Ig}' \ {} + Indentation fixed up manually afterwards. Some of the lines were manually edited to reduce the line length to below 80 charecters. Some of the lines with newlines in the middle of the string were also manually edit to avoid checkpatch errrors. The #include lines were manually updated to allow the code to compile. Several of the warning messages can be improved after this patch, to keep this patch mechanical this has been moved into a later patch. Signed-off-by: Alistair Francis <alistair.francis@xilinx.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Kevin Wolf <kwolf@redhat.com> Cc: Max Reitz <mreitz@redhat.com> Cc: "Michael S. Tsirkin" <mst@redhat.com> Cc: Igor Mammedov <imammedo@redhat.com> Cc: Peter Maydell <peter.maydell@linaro.org> Cc: Stefano Stabellini <sstabellini@kernel.org> Cc: Anthony Perard <anthony.perard@citrix.com> Cc: Richard Henderson <rth@twiddle.net> Cc: Eduardo Habkost <ehabkost@redhat.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: Yongbok Kim <yongbok.kim@imgtec.com> Cc: Cornelia Huck <cohuck@redhat.com> Cc: Christian Borntraeger <borntraeger@de.ibm.com> Cc: Alexander Graf <agraf@suse.de> Cc: Jason Wang <jasowang@redhat.com> Cc: David Gibson <david@gibson.dropbear.id.au> Cc: Gerd Hoffmann <kraxel@redhat.com> Acked-by: Cornelia Huck <cohuck@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> Message-Id: <5def63849ca8f551630c6f2b45bcb1c482f765a6.1505158760.git.alistair.francis@xilinx.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
314 lines
9.6 KiB
C
314 lines
9.6 KiB
C
/*
|
|
* QEMU/MIPS pseudo-board
|
|
*
|
|
* emulates a simple machine with ISA-like bus.
|
|
* ISA IO space mapped to the 0x14000000 (PHYS) and
|
|
* ISA memory at the 0x10000000 (PHYS, 16Mb in size).
|
|
* All peripherial devices are attached to this "bus" with
|
|
* the standard PC ISA addresses.
|
|
*/
|
|
#include "qemu/osdep.h"
|
|
#include "qapi/error.h"
|
|
#include "qemu-common.h"
|
|
#include "cpu.h"
|
|
#include "hw/hw.h"
|
|
#include "hw/mips/mips.h"
|
|
#include "hw/mips/cpudevs.h"
|
|
#include "hw/i386/pc.h"
|
|
#include "hw/char/serial.h"
|
|
#include "hw/isa/isa.h"
|
|
#include "net/net.h"
|
|
#include "sysemu/sysemu.h"
|
|
#include "hw/boards.h"
|
|
#include "hw/block/flash.h"
|
|
#include "qemu/log.h"
|
|
#include "hw/mips/bios.h"
|
|
#include "hw/ide.h"
|
|
#include "hw/loader.h"
|
|
#include "elf.h"
|
|
#include "hw/timer/mc146818rtc.h"
|
|
#include "hw/timer/i8254.h"
|
|
#include "sysemu/block-backend.h"
|
|
#include "exec/address-spaces.h"
|
|
#include "sysemu/qtest.h"
|
|
#include "qemu/error-report.h"
|
|
|
|
#define MAX_IDE_BUS 2
|
|
|
|
static const int ide_iobase[2] = { 0x1f0, 0x170 };
|
|
static const int ide_iobase2[2] = { 0x3f6, 0x376 };
|
|
static const int ide_irq[2] = { 14, 15 };
|
|
|
|
static ISADevice *pit; /* PIT i8254 */
|
|
|
|
/* i8254 PIT is attached to the IRQ0 at PIC i8259 */
|
|
|
|
static struct _loaderparams {
|
|
int ram_size;
|
|
const char *kernel_filename;
|
|
const char *kernel_cmdline;
|
|
const char *initrd_filename;
|
|
} loaderparams;
|
|
|
|
static void mips_qemu_write (void *opaque, hwaddr addr,
|
|
uint64_t val, unsigned size)
|
|
{
|
|
if ((addr & 0xffff) == 0 && val == 42)
|
|
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
|
|
else if ((addr & 0xffff) == 4 && val == 42)
|
|
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
|
|
}
|
|
|
|
static uint64_t mips_qemu_read (void *opaque, hwaddr addr,
|
|
unsigned size)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static const MemoryRegionOps mips_qemu_ops = {
|
|
.read = mips_qemu_read,
|
|
.write = mips_qemu_write,
|
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
|
};
|
|
|
|
typedef struct ResetData {
|
|
MIPSCPU *cpu;
|
|
uint64_t vector;
|
|
} ResetData;
|
|
|
|
static int64_t load_kernel(void)
|
|
{
|
|
int64_t entry, kernel_high;
|
|
long kernel_size, initrd_size, params_size;
|
|
ram_addr_t initrd_offset;
|
|
uint32_t *params_buf;
|
|
int big_endian;
|
|
|
|
#ifdef TARGET_WORDS_BIGENDIAN
|
|
big_endian = 1;
|
|
#else
|
|
big_endian = 0;
|
|
#endif
|
|
kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
|
|
NULL, (uint64_t *)&entry, NULL,
|
|
(uint64_t *)&kernel_high, big_endian,
|
|
EM_MIPS, 1, 0);
|
|
if (kernel_size >= 0) {
|
|
if ((entry & ~0x7fffffffULL) == 0x80000000)
|
|
entry = (int32_t)entry;
|
|
} else {
|
|
error_report("qemu: could not load kernel '%s': %s",
|
|
loaderparams.kernel_filename,
|
|
load_elf_strerror(kernel_size));
|
|
exit(1);
|
|
}
|
|
|
|
/* load initrd */
|
|
initrd_size = 0;
|
|
initrd_offset = 0;
|
|
if (loaderparams.initrd_filename) {
|
|
initrd_size = get_image_size (loaderparams.initrd_filename);
|
|
if (initrd_size > 0) {
|
|
initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & INITRD_PAGE_MASK;
|
|
if (initrd_offset + initrd_size > ram_size) {
|
|
fprintf(stderr,
|
|
"qemu: memory too small for initial ram disk '%s'\n",
|
|
loaderparams.initrd_filename);
|
|
exit(1);
|
|
}
|
|
initrd_size = load_image_targphys(loaderparams.initrd_filename,
|
|
initrd_offset,
|
|
ram_size - initrd_offset);
|
|
}
|
|
if (initrd_size == (target_ulong) -1) {
|
|
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
|
|
loaderparams.initrd_filename);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
/* Store command line. */
|
|
params_size = 264;
|
|
params_buf = g_malloc(params_size);
|
|
|
|
params_buf[0] = tswap32(ram_size);
|
|
params_buf[1] = tswap32(0x12345678);
|
|
|
|
if (initrd_size > 0) {
|
|
snprintf((char *)params_buf + 8, 256, "rd_start=0x%" PRIx64 " rd_size=%li %s",
|
|
cpu_mips_phys_to_kseg0(NULL, initrd_offset),
|
|
initrd_size, loaderparams.kernel_cmdline);
|
|
} else {
|
|
snprintf((char *)params_buf + 8, 256, "%s", loaderparams.kernel_cmdline);
|
|
}
|
|
|
|
rom_add_blob_fixed("params", params_buf, params_size,
|
|
(16 << 20) - 264);
|
|
|
|
g_free(params_buf);
|
|
return entry;
|
|
}
|
|
|
|
static void main_cpu_reset(void *opaque)
|
|
{
|
|
ResetData *s = (ResetData *)opaque;
|
|
CPUMIPSState *env = &s->cpu->env;
|
|
|
|
cpu_reset(CPU(s->cpu));
|
|
env->active_tc.PC = s->vector;
|
|
}
|
|
|
|
static const int sector_len = 32 * 1024;
|
|
static
|
|
void mips_r4k_init(MachineState *machine)
|
|
{
|
|
ram_addr_t ram_size = machine->ram_size;
|
|
const char *cpu_model = machine->cpu_model;
|
|
const char *kernel_filename = machine->kernel_filename;
|
|
const char *kernel_cmdline = machine->kernel_cmdline;
|
|
const char *initrd_filename = machine->initrd_filename;
|
|
char *filename;
|
|
MemoryRegion *address_space_mem = get_system_memory();
|
|
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
|
MemoryRegion *bios;
|
|
MemoryRegion *iomem = g_new(MemoryRegion, 1);
|
|
MemoryRegion *isa_io = g_new(MemoryRegion, 1);
|
|
MemoryRegion *isa_mem = g_new(MemoryRegion, 1);
|
|
int bios_size;
|
|
MIPSCPU *cpu;
|
|
CPUMIPSState *env;
|
|
ResetData *reset_info;
|
|
int i;
|
|
qemu_irq *i8259;
|
|
ISABus *isa_bus;
|
|
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
|
|
DriveInfo *dinfo;
|
|
int be;
|
|
|
|
/* init CPUs */
|
|
if (cpu_model == NULL) {
|
|
#ifdef TARGET_MIPS64
|
|
cpu_model = "R4000";
|
|
#else
|
|
cpu_model = "24Kf";
|
|
#endif
|
|
}
|
|
cpu = cpu_mips_init(cpu_model);
|
|
if (cpu == NULL) {
|
|
fprintf(stderr, "Unable to find CPU definition\n");
|
|
exit(1);
|
|
}
|
|
env = &cpu->env;
|
|
|
|
reset_info = g_malloc0(sizeof(ResetData));
|
|
reset_info->cpu = cpu;
|
|
reset_info->vector = env->active_tc.PC;
|
|
qemu_register_reset(main_cpu_reset, reset_info);
|
|
|
|
/* allocate RAM */
|
|
if (ram_size > (256 << 20)) {
|
|
fprintf(stderr,
|
|
"qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
|
|
((unsigned int)ram_size / (1 << 20)));
|
|
exit(1);
|
|
}
|
|
memory_region_allocate_system_memory(ram, NULL, "mips_r4k.ram", ram_size);
|
|
|
|
memory_region_add_subregion(address_space_mem, 0, ram);
|
|
|
|
memory_region_init_io(iomem, NULL, &mips_qemu_ops, NULL, "mips-qemu", 0x10000);
|
|
memory_region_add_subregion(address_space_mem, 0x1fbf0000, iomem);
|
|
|
|
/* Try to load a BIOS image. If this fails, we continue regardless,
|
|
but initialize the hardware ourselves. When a kernel gets
|
|
preloaded we also initialize the hardware, since the BIOS wasn't
|
|
run. */
|
|
if (bios_name == NULL)
|
|
bios_name = BIOS_FILENAME;
|
|
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
|
|
if (filename) {
|
|
bios_size = get_image_size(filename);
|
|
} else {
|
|
bios_size = -1;
|
|
}
|
|
#ifdef TARGET_WORDS_BIGENDIAN
|
|
be = 1;
|
|
#else
|
|
be = 0;
|
|
#endif
|
|
if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
|
|
bios = g_new(MemoryRegion, 1);
|
|
memory_region_init_ram(bios, NULL, "mips_r4k.bios", BIOS_SIZE,
|
|
&error_fatal);
|
|
memory_region_set_readonly(bios, true);
|
|
memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios);
|
|
|
|
load_image_targphys(filename, 0x1fc00000, BIOS_SIZE);
|
|
} else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
|
|
uint32_t mips_rom = 0x00400000;
|
|
if (!pflash_cfi01_register(0x1fc00000, NULL, "mips_r4k.bios", mips_rom,
|
|
blk_by_legacy_dinfo(dinfo),
|
|
sector_len, mips_rom / sector_len,
|
|
4, 0, 0, 0, 0, be)) {
|
|
fprintf(stderr, "qemu: Error registering flash memory.\n");
|
|
}
|
|
} else if (!qtest_enabled()) {
|
|
/* not fatal */
|
|
warn_report("could not load MIPS bios '%s'",
|
|
bios_name);
|
|
}
|
|
g_free(filename);
|
|
|
|
if (kernel_filename) {
|
|
loaderparams.ram_size = ram_size;
|
|
loaderparams.kernel_filename = kernel_filename;
|
|
loaderparams.kernel_cmdline = kernel_cmdline;
|
|
loaderparams.initrd_filename = initrd_filename;
|
|
reset_info->vector = load_kernel();
|
|
}
|
|
|
|
/* Init CPU internal devices */
|
|
cpu_mips_irq_init_cpu(cpu);
|
|
cpu_mips_clock_init(cpu);
|
|
|
|
/* ISA bus: IO space at 0x14000000, mem space at 0x10000000 */
|
|
memory_region_init_alias(isa_io, NULL, "isa-io",
|
|
get_system_io(), 0, 0x00010000);
|
|
memory_region_init(isa_mem, NULL, "isa-mem", 0x01000000);
|
|
memory_region_add_subregion(get_system_memory(), 0x14000000, isa_io);
|
|
memory_region_add_subregion(get_system_memory(), 0x10000000, isa_mem);
|
|
isa_bus = isa_bus_new(NULL, isa_mem, get_system_io(), &error_abort);
|
|
|
|
/* The PIC is attached to the MIPS CPU INT0 pin */
|
|
i8259 = i8259_init(isa_bus, env->irq[2]);
|
|
isa_bus_irqs(isa_bus, i8259);
|
|
|
|
rtc_init(isa_bus, 2000, NULL);
|
|
|
|
pit = pit_init(isa_bus, 0x40, 0, NULL);
|
|
|
|
serial_hds_isa_init(isa_bus, 0, MAX_SERIAL_PORTS);
|
|
|
|
isa_vga_init(isa_bus);
|
|
|
|
if (nd_table[0].used)
|
|
isa_ne2000_init(isa_bus, 0x300, 9, &nd_table[0]);
|
|
|
|
ide_drive_get(hd, ARRAY_SIZE(hd));
|
|
for(i = 0; i < MAX_IDE_BUS; i++)
|
|
isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i],
|
|
hd[MAX_IDE_DEVS * i],
|
|
hd[MAX_IDE_DEVS * i + 1]);
|
|
|
|
isa_create_simple(isa_bus, "i8042");
|
|
}
|
|
|
|
static void mips_machine_init(MachineClass *mc)
|
|
{
|
|
mc->desc = "mips r4k platform";
|
|
mc->init = mips_r4k_init;
|
|
mc->block_default_type = IF_IDE;
|
|
}
|
|
|
|
DEFINE_MACHINE("mips", mips_machine_init)
|