2006-12-07 05:38:37 +08:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2016-01-19 01:35:00 +08:00
|
|
|
#include "qemu/osdep.h"
|
2018-06-25 20:42:22 +08:00
|
|
|
#include "qemu/units.h"
|
include/qemu/osdep.h: Don't include qapi/error.h
Commit 57cb38b included qapi/error.h into qemu/osdep.h to get the
Error typedef. Since then, we've moved to include qemu/osdep.h
everywhere. Its file comment explains: "To avoid getting into
possible circular include dependencies, this file should not include
any other QEMU headers, with the exceptions of config-host.h,
compiler.h, os-posix.h and os-win32.h, all of which are doing a
similar job to this file and are under similar constraints."
qapi/error.h doesn't do a similar job, and it doesn't adhere to
similar constraints: it includes qapi-types.h. That's in excess of
100KiB of crap most .c files don't actually need.
Add the typedef to qemu/typedefs.h, and include that instead of
qapi/error.h. Include qapi/error.h in .c files that need it and don't
get it now. Include qapi-types.h in qom/object.h for uint16List.
Update scripts/clean-includes accordingly. Update it further to match
reality: replace config.h by config-target.h, add sysemu/os-posix.h,
sysemu/os-win32.h. Update the list of includes in the qemu/osdep.h
comment quoted above similarly.
This reduces the number of objects depending on qapi/error.h from "all
of them" to less than a third. Unfortunately, the number depending on
qapi-types.h shrinks only a little. More work is needed for that one.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
[Fix compilation without the spice devel packages. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2016-03-14 16:01:28 +08:00
|
|
|
#include "qapi/error.h"
|
2016-01-20 04:51:44 +08:00
|
|
|
#include "qemu-common.h"
|
|
|
|
#include "cpu.h"
|
2013-02-04 22:40:22 +08:00
|
|
|
#include "hw/hw.h"
|
2013-02-06 00:06:20 +08:00
|
|
|
#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"
|
2012-10-24 14:43:34 +08:00
|
|
|
#include "net/net.h"
|
2017-10-18 00:44:22 +08:00
|
|
|
#include "hw/net/ne2000-isa.h"
|
2012-12-18 01:20:04 +08:00
|
|
|
#include "sysemu/sysemu.h"
|
2013-02-04 22:40:22 +08:00
|
|
|
#include "hw/boards.h"
|
2013-02-06 00:06:20 +08:00
|
|
|
#include "hw/block/flash.h"
|
2012-12-18 01:20:00 +08:00
|
|
|
#include "qemu/log.h"
|
2013-02-06 00:06:20 +08:00
|
|
|
#include "hw/mips/bios.h"
|
2013-02-04 22:40:22 +08:00
|
|
|
#include "hw/ide.h"
|
|
|
|
#include "hw/loader.h"
|
2009-09-20 22:58:02 +08:00
|
|
|
#include "elf.h"
|
2013-02-06 00:06:20 +08:00
|
|
|
#include "hw/timer/mc146818rtc.h"
|
2018-03-09 06:39:24 +08:00
|
|
|
#include "hw/input/i8042.h"
|
2013-02-06 00:06:20 +08:00
|
|
|
#include "hw/timer/i8254.h"
|
2012-12-18 01:19:49 +08:00
|
|
|
#include "exec/address-spaces.h"
|
2013-07-29 22:05:33 +08:00
|
|
|
#include "sysemu/qtest.h"
|
2017-07-27 07:56:13 +08:00
|
|
|
#include "qemu/error-report.h"
|
2007-01-25 06:00:13 +08:00
|
|
|
|
2007-12-02 12:51:10 +08:00
|
|
|
#define MAX_IDE_BUS 2
|
|
|
|
|
2006-10-29 23:38:28 +08:00
|
|
|
static const int ide_iobase[2] = { 0x1f0, 0x170 };
|
|
|
|
static const int ide_iobase2[2] = { 0x3f6, 0x376 };
|
|
|
|
static const int ide_irq[2] = { 14, 15 };
|
|
|
|
|
2011-02-14 03:54:40 +08:00
|
|
|
static ISADevice *pit; /* PIT i8254 */
|
2005-08-21 17:41:56 +08:00
|
|
|
|
2007-12-07 09:13:37 +08:00
|
|
|
/* i8254 PIT is attached to the IRQ0 at PIC i8259 */
|
2005-07-02 22:58:51 +08:00
|
|
|
|
2007-11-10 01:52:11 +08:00
|
|
|
static struct _loaderparams {
|
|
|
|
int ram_size;
|
|
|
|
const char *kernel_filename;
|
|
|
|
const char *kernel_cmdline;
|
|
|
|
const char *initrd_filename;
|
|
|
|
} loaderparams;
|
|
|
|
|
2012-10-23 18:30:10 +08:00
|
|
|
static void mips_qemu_write (void *opaque, hwaddr addr,
|
2011-08-09 03:22:38 +08:00
|
|
|
uint64_t val, unsigned size)
|
2006-12-07 01:48:52 +08:00
|
|
|
{
|
|
|
|
if ((addr & 0xffff) == 0 && val == 42)
|
2017-05-16 05:41:13 +08:00
|
|
|
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
|
2006-12-07 01:48:52 +08:00
|
|
|
else if ((addr & 0xffff) == 4 && val == 42)
|
2017-05-16 05:41:13 +08:00
|
|
|
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
|
2006-12-07 01:48:52 +08:00
|
|
|
}
|
|
|
|
|
2012-10-23 18:30:10 +08:00
|
|
|
static uint64_t mips_qemu_read (void *opaque, hwaddr addr,
|
2011-08-09 03:22:38 +08:00
|
|
|
unsigned size)
|
2006-12-07 01:48:52 +08:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-08-09 03:22:38 +08:00
|
|
|
static const MemoryRegionOps mips_qemu_ops = {
|
|
|
|
.read = mips_qemu_read,
|
|
|
|
.write = mips_qemu_write,
|
|
|
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
2006-12-07 01:48:52 +08:00
|
|
|
};
|
|
|
|
|
2009-11-14 08:04:29 +08:00
|
|
|
typedef struct ResetData {
|
2012-05-05 20:23:25 +08:00
|
|
|
MIPSCPU *cpu;
|
2009-11-14 08:04:29 +08:00
|
|
|
uint64_t vector;
|
|
|
|
} ResetData;
|
|
|
|
|
|
|
|
static int64_t load_kernel(void)
|
2006-12-07 01:48:52 +08:00
|
|
|
{
|
2018-06-25 20:42:21 +08:00
|
|
|
const size_t params_size = 264;
|
2018-09-13 18:07:13 +08:00
|
|
|
int64_t entry, kernel_high, initrd_size;
|
|
|
|
long kernel_size;
|
2009-10-02 05:12:16 +08:00
|
|
|
ram_addr_t initrd_offset;
|
2009-11-16 06:04:20 +08:00
|
|
|
uint32_t *params_buf;
|
2009-09-20 22:58:02 +08:00
|
|
|
int big_endian;
|
2006-12-07 01:48:52 +08:00
|
|
|
|
2009-09-20 22:58:02 +08:00
|
|
|
#ifdef TARGET_WORDS_BIGENDIAN
|
|
|
|
big_endian = 1;
|
|
|
|
#else
|
|
|
|
big_endian = 0;
|
|
|
|
#endif
|
2019-01-15 20:18:03 +08:00
|
|
|
kernel_size = load_elf(loaderparams.kernel_filename, NULL,
|
|
|
|
cpu_mips_kseg0_to_phys, NULL,
|
|
|
|
(uint64_t *)&entry, NULL,
|
2010-03-15 04:20:59 +08:00
|
|
|
(uint64_t *)&kernel_high, big_endian,
|
2016-03-04 19:30:21 +08:00
|
|
|
EM_MIPS, 1, 0);
|
2006-12-21 09:19:56 +08:00
|
|
|
if (kernel_size >= 0) {
|
|
|
|
if ((entry & ~0x7fffffffULL) == 0x80000000)
|
2006-12-21 21:48:28 +08:00
|
|
|
entry = (int32_t)entry;
|
2006-12-21 09:19:56 +08:00
|
|
|
} else {
|
hw/mips: Replace fprintf(stderr, "*\n" with error_report()
Replace a large number of the fprintf(stderr, "*\n" calls with
error_report(). The functions were renamed with these commands and then
compiler issues where manually fixed.
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
Some lines where then manually tweaked to pass checkpatch.
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Yongbok Kim <yongbok.kim@imgtec.com>
Cc: "Hervé Poussineau" <hpoussin@reactos.org>
Conversions that aren't followed by exit() dropped, because they might
be inappropriate.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20180203084315.20497-6-armbru@redhat.com>
2018-02-03 16:43:06 +08:00
|
|
|
error_report("could not load kernel '%s': %s",
|
2017-07-27 07:56:13 +08:00
|
|
|
loaderparams.kernel_filename,
|
|
|
|
load_elf_strerror(kernel_size));
|
2006-12-23 22:18:40 +08:00
|
|
|
exit(1);
|
2006-12-07 01:48:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* load initrd */
|
|
|
|
initrd_size = 0;
|
2007-04-02 01:56:37 +08:00
|
|
|
initrd_offset = 0;
|
2007-11-10 01:52:11 +08:00
|
|
|
if (loaderparams.initrd_filename) {
|
|
|
|
initrd_size = get_image_size (loaderparams.initrd_filename);
|
2007-04-02 01:56:37 +08:00
|
|
|
if (initrd_size > 0) {
|
2013-06-27 15:35:27 +08:00
|
|
|
initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & INITRD_PAGE_MASK;
|
2007-04-02 01:56:37 +08:00
|
|
|
if (initrd_offset + initrd_size > ram_size) {
|
hw/mips: Replace fprintf(stderr, "*\n" with error_report()
Replace a large number of the fprintf(stderr, "*\n" calls with
error_report(). The functions were renamed with these commands and then
compiler issues where manually fixed.
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
Some lines where then manually tweaked to pass checkpatch.
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Yongbok Kim <yongbok.kim@imgtec.com>
Cc: "Hervé Poussineau" <hpoussin@reactos.org>
Conversions that aren't followed by exit() dropped, because they might
be inappropriate.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20180203084315.20497-6-armbru@redhat.com>
2018-02-03 16:43:06 +08:00
|
|
|
error_report("memory too small for initial ram disk '%s'",
|
|
|
|
loaderparams.initrd_filename);
|
2007-04-02 01:56:37 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2009-04-10 04:05:49 +08:00
|
|
|
initrd_size = load_image_targphys(loaderparams.initrd_filename,
|
|
|
|
initrd_offset,
|
|
|
|
ram_size - initrd_offset);
|
2007-04-02 01:56:37 +08:00
|
|
|
}
|
2006-12-07 01:48:52 +08:00
|
|
|
if (initrd_size == (target_ulong) -1) {
|
hw/mips: Replace fprintf(stderr, "*\n" with error_report()
Replace a large number of the fprintf(stderr, "*\n" calls with
error_report(). The functions were renamed with these commands and then
compiler issues where manually fixed.
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
Some lines where then manually tweaked to pass checkpatch.
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Yongbok Kim <yongbok.kim@imgtec.com>
Cc: "Hervé Poussineau" <hpoussin@reactos.org>
Conversions that aren't followed by exit() dropped, because they might
be inappropriate.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20180203084315.20497-6-armbru@redhat.com>
2018-02-03 16:43:06 +08:00
|
|
|
error_report("could not load initial ram disk '%s'",
|
|
|
|
loaderparams.initrd_filename);
|
2006-12-07 01:48:52 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Store command line. */
|
2011-08-21 11:09:37 +08:00
|
|
|
params_buf = g_malloc(params_size);
|
2009-11-16 06:04:20 +08:00
|
|
|
|
|
|
|
params_buf[0] = tswap32(ram_size);
|
|
|
|
params_buf[1] = tswap32(0x12345678);
|
|
|
|
|
2006-12-07 01:48:52 +08:00
|
|
|
if (initrd_size > 0) {
|
2018-09-13 18:07:13 +08:00
|
|
|
snprintf((char *)params_buf + 8, 256, "rd_start=0x%" PRIx64 " rd_size=%" PRId64 " %s",
|
2010-03-15 04:20:59 +08:00
|
|
|
cpu_mips_phys_to_kseg0(NULL, initrd_offset),
|
2009-11-16 06:04:20 +08:00
|
|
|
initrd_size, loaderparams.kernel_cmdline);
|
2009-04-10 11:36:49 +08:00
|
|
|
} else {
|
2009-11-16 06:04:20 +08:00
|
|
|
snprintf((char *)params_buf + 8, 256, "%s", loaderparams.kernel_cmdline);
|
2006-12-07 01:48:52 +08:00
|
|
|
}
|
|
|
|
|
2009-11-16 06:04:20 +08:00
|
|
|
rom_add_blob_fixed("params", params_buf, params_size,
|
2018-06-25 20:42:22 +08:00
|
|
|
16 * MiB - params_size);
|
2009-11-16 06:04:20 +08:00
|
|
|
|
2015-04-28 17:11:02 +08:00
|
|
|
g_free(params_buf);
|
2009-11-14 08:04:29 +08:00
|
|
|
return entry;
|
2006-12-07 01:48:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void main_cpu_reset(void *opaque)
|
|
|
|
{
|
2009-11-14 08:04:29 +08:00
|
|
|
ResetData *s = (ResetData *)opaque;
|
2012-05-05 20:23:25 +08:00
|
|
|
CPUMIPSState *env = &s->cpu->env;
|
2006-12-07 01:48:52 +08:00
|
|
|
|
2012-05-05 20:23:25 +08:00
|
|
|
cpu_reset(CPU(s->cpu));
|
2009-11-14 08:04:29 +08:00
|
|
|
env->active_tc.PC = s->vector;
|
2006-12-07 01:48:52 +08:00
|
|
|
}
|
2006-04-27 06:06:55 +08:00
|
|
|
|
2018-06-25 20:42:22 +08:00
|
|
|
static const int sector_len = 32 * KiB;
|
2007-02-18 08:10:59 +08:00
|
|
|
static
|
2014-05-07 22:42:57 +08:00
|
|
|
void mips_r4k_init(MachineState *machine)
|
2005-07-02 22:58:51 +08:00
|
|
|
{
|
2014-05-07 22:42:57 +08:00
|
|
|
ram_addr_t ram_size = machine->ram_size;
|
|
|
|
const char *kernel_filename = machine->kernel_filename;
|
|
|
|
const char *kernel_cmdline = machine->kernel_cmdline;
|
|
|
|
const char *initrd_filename = machine->initrd_filename;
|
2009-05-30 07:52:44 +08:00
|
|
|
char *filename;
|
2011-08-09 03:22:38 +08:00
|
|
|
MemoryRegion *address_space_mem = get_system_memory();
|
|
|
|
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
2011-08-04 20:55:30 +08:00
|
|
|
MemoryRegion *bios;
|
2011-08-09 03:22:38 +08:00
|
|
|
MemoryRegion *iomem = g_new(MemoryRegion, 1);
|
2015-02-01 16:12:53 +08:00
|
|
|
MemoryRegion *isa_io = g_new(MemoryRegion, 1);
|
|
|
|
MemoryRegion *isa_mem = g_new(MemoryRegion, 1);
|
2007-01-06 09:37:51 +08:00
|
|
|
int bios_size;
|
2012-05-05 20:21:43 +08:00
|
|
|
MIPSCPU *cpu;
|
2012-03-14 08:38:23 +08:00
|
|
|
CPUMIPSState *env;
|
2009-11-14 08:04:29 +08:00
|
|
|
ResetData *reset_info;
|
2006-10-29 23:38:28 +08:00
|
|
|
int i;
|
2007-04-08 02:14:41 +08:00
|
|
|
qemu_irq *i8259;
|
2011-12-16 05:09:51 +08:00
|
|
|
ISABus *isa_bus;
|
2009-08-28 21:47:03 +08:00
|
|
|
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
|
2009-07-22 22:42:57 +08:00
|
|
|
DriveInfo *dinfo;
|
2010-03-30 03:23:56 +08:00
|
|
|
int be;
|
2005-11-22 07:33:12 +08:00
|
|
|
|
2007-03-18 08:30:29 +08:00
|
|
|
/* init CPUs */
|
2017-10-05 21:51:14 +08:00
|
|
|
cpu = MIPS_CPU(cpu_create(machine->cpu_type));
|
2012-05-05 20:21:43 +08:00
|
|
|
env = &cpu->env;
|
|
|
|
|
2011-08-21 11:09:37 +08:00
|
|
|
reset_info = g_malloc0(sizeof(ResetData));
|
2012-05-05 20:23:25 +08:00
|
|
|
reset_info->cpu = cpu;
|
2009-11-14 08:04:29 +08:00
|
|
|
reset_info->vector = env->active_tc.PC;
|
|
|
|
qemu_register_reset(main_cpu_reset, reset_info);
|
2005-11-22 07:33:12 +08:00
|
|
|
|
2005-07-02 22:58:51 +08:00
|
|
|
/* allocate RAM */
|
2018-06-25 20:42:22 +08:00
|
|
|
if (ram_size > 256 * MiB) {
|
|
|
|
error_report("Too much memory for this machine: %" PRId64 "MB,"
|
|
|
|
" maximum 256MB", ram_size / MiB);
|
2009-01-24 23:07:25 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2015-03-25 05:28:15 +08:00
|
|
|
memory_region_allocate_system_memory(ram, NULL, "mips_r4k.ram", ram_size);
|
2009-04-10 04:05:49 +08:00
|
|
|
|
2011-08-09 03:22:38 +08:00
|
|
|
memory_region_add_subregion(address_space_mem, 0, ram);
|
2006-04-27 06:06:55 +08:00
|
|
|
|
2013-06-06 17:41:28 +08:00
|
|
|
memory_region_init_io(iomem, NULL, &mips_qemu_ops, NULL, "mips-qemu", 0x10000);
|
2011-08-09 03:22:38 +08:00
|
|
|
memory_region_add_subregion(address_space_mem, 0x1fbf0000, iomem);
|
2006-12-07 01:48:52 +08:00
|
|
|
|
2006-04-27 06:06:55 +08:00
|
|
|
/* 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. */
|
2007-10-05 21:08:35 +08:00
|
|
|
if (bios_name == NULL)
|
|
|
|
bios_name = BIOS_FILENAME;
|
2009-05-30 07:52:44 +08:00
|
|
|
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
|
|
|
|
if (filename) {
|
|
|
|
bios_size = get_image_size(filename);
|
|
|
|
} else {
|
|
|
|
bios_size = -1;
|
|
|
|
}
|
2010-03-30 03:23:56 +08:00
|
|
|
#ifdef TARGET_WORDS_BIGENDIAN
|
|
|
|
be = 1;
|
|
|
|
#else
|
|
|
|
be = 0;
|
|
|
|
#endif
|
2007-01-06 10:24:15 +08:00
|
|
|
if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
|
2011-08-04 20:55:30 +08:00
|
|
|
bios = g_new(MemoryRegion, 1);
|
2017-07-07 22:42:53 +08:00
|
|
|
memory_region_init_ram(bios, NULL, "mips_r4k.bios", BIOS_SIZE,
|
Fix bad error handling after memory_region_init_ram()
Symptom:
$ qemu-system-x86_64 -m 10000000
Unexpected error in ram_block_add() at /work/armbru/qemu/exec.c:1456:
upstream-qemu: cannot set up guest memory 'pc.ram': Cannot allocate memory
Aborted (core dumped)
Root cause: commit ef701d7 screwed up handling of out-of-memory
conditions. Before the commit, we report the error and exit(1), in
one place, ram_block_add(). The commit lifts the error handling up
the call chain some, to three places. Fine. Except it uses
&error_abort in these places, changing the behavior from exit(1) to
abort(), and thus undoing the work of commit 3922825 "exec: Don't
abort when we can't allocate guest memory".
The three places are:
* memory_region_init_ram()
Commit 4994653 (right after commit ef701d7) lifted the error
handling further, through memory_region_init_ram(), multiplying the
incorrect use of &error_abort. Later on, imitation of existing
(bad) code may have created more.
* memory_region_init_ram_ptr()
The &error_abort is still there.
* memory_region_init_rom_device()
Doesn't need fixing, because commit 33e0eb5 (soon after commit
ef701d7) lifted the error handling further, and in the process
changed it from &error_abort to passing it up the call chain.
Correct, because the callers are realize() methods.
Fix the error handling after memory_region_init_ram() with a
Coccinelle semantic patch:
@r@
expression mr, owner, name, size, err;
position p;
@@
memory_region_init_ram(mr, owner, name, size,
(
- &error_abort
+ &error_fatal
|
err@p
)
);
@script:python@
p << r.p;
@@
print "%s:%s:%s" % (p[0].file, p[0].line, p[0].column)
When the last argument is &error_abort, it gets replaced by
&error_fatal. This is the fix.
If the last argument is anything else, its position is reported. This
lets us check the fix is complete. Four positions get reported:
* ram_backend_memory_alloc()
Error is passed up the call chain, ultimately through
user_creatable_complete(). As far as I can tell, it's callers all
handle the error sanely.
* fsl_imx25_realize(), fsl_imx31_realize(), dp8393x_realize()
DeviceClass.realize() methods, errors handled sanely further up the
call chain.
We're good. Test case again behaves:
$ qemu-system-x86_64 -m 10000000
qemu-system-x86_64: cannot set up guest memory 'pc.ram': Cannot allocate memory
[Exit 1 ]
The next commits will repair the rest of commit ef701d7's damage.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <1441983105-26376-3-git-send-email-armbru@redhat.com>
Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
2015-09-11 22:51:43 +08:00
|
|
|
&error_fatal);
|
2011-08-04 20:55:30 +08:00
|
|
|
memory_region_set_readonly(bios, true);
|
|
|
|
memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios);
|
2011-08-26 03:39:18 +08:00
|
|
|
|
2009-05-30 07:52:44 +08:00
|
|
|
load_image_targphys(filename, 0x1fc00000, BIOS_SIZE);
|
2009-07-22 22:42:57 +08:00
|
|
|
} else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
|
2008-04-20 14:28:28 +08:00
|
|
|
uint32_t mips_rom = 0x00400000;
|
2019-03-08 17:46:09 +08:00
|
|
|
if (!pflash_cfi01_register(0x1fc00000, "mips_r4k.bios", mips_rom,
|
2014-10-07 19:59:18 +08:00
|
|
|
blk_by_legacy_dinfo(dinfo),
|
2019-03-08 17:46:10 +08:00
|
|
|
sector_len, 4, 0, 0, 0, 0, be)) {
|
2008-04-20 14:28:28 +08:00
|
|
|
fprintf(stderr, "qemu: Error registering flash memory.\n");
|
2018-12-14 06:37:37 +08:00
|
|
|
}
|
2013-07-29 22:05:33 +08:00
|
|
|
} else if (!qtest_enabled()) {
|
2017-09-12 03:52:53 +08:00
|
|
|
/* not fatal */
|
2017-09-12 03:52:56 +08:00
|
|
|
warn_report("could not load MIPS bios '%s'", bios_name);
|
2009-05-30 07:52:44 +08:00
|
|
|
}
|
2015-08-26 19:17:18 +08:00
|
|
|
g_free(filename);
|
2006-04-27 06:06:55 +08:00
|
|
|
|
|
|
|
if (kernel_filename) {
|
2007-11-10 01:52:11 +08:00
|
|
|
loaderparams.ram_size = ram_size;
|
|
|
|
loaderparams.kernel_filename = kernel_filename;
|
|
|
|
loaderparams.kernel_cmdline = kernel_cmdline;
|
|
|
|
loaderparams.initrd_filename = initrd_filename;
|
2009-11-14 08:04:29 +08:00
|
|
|
reset_info->vector = load_kernel();
|
2005-07-02 22:58:51 +08:00
|
|
|
}
|
|
|
|
|
2006-12-07 05:38:37 +08:00
|
|
|
/* Init CPU internal devices */
|
2016-03-15 21:32:19 +08:00
|
|
|
cpu_mips_irq_init_cpu(cpu);
|
|
|
|
cpu_mips_clock_init(cpu);
|
2005-07-02 22:58:51 +08:00
|
|
|
|
2015-02-01 16:12:53 +08:00
|
|
|
/* 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: Clean up error handling around isa_bus_new()
We can have at most one ISA bus. If you try to create another one,
isa_bus_new() complains to stderr and returns null.
isa_bus_new() is called in two contexts, machine's init() and device's
realize() methods. Since complaining to stderr is not proper in the
latter context, convert isa_bus_new() to Error.
Machine's init():
* mips_jazz_init(), called from the init() methods of machines
"magnum" and "pica"
* mips_r4k_init(), the init() method of machine "mips"
* pc_init1() called from the init() methods of non-q35 PC machines
* typhoon_init(), called from clipper_init(), the init() method of
machine "clipper"
These callers always create the first ISA bus, hence isa_bus_new()
can't fail. Simply pass &error_abort.
Device's realize():
* i82378_realize(), of PCI device "i82378"
* ich9_lpc_realize(), of PCI device "ICH9-LPC"
* pci_ebus_realize(), of PCI device "ebus"
* piix3_realize(), of PCI device "pci-piix3", abstract parent of
"PIIX3" and "PIIX3-xen"
* piix4_realize(), of PCI device "PIIX4"
* vt82c686b_realize(), of PCI device "VT82C686B"
Propagate the error. Note that these devices are typically created
only by machine init() methods with qdev_init_nofail() or similar. If
we screwed up and created an ISA bus before that call, we now give up
right away. Before, we'd hobble on, and typically die in
isa_bus_irqs(). Similar if someone finds a way to hot-plug one of
these critters.
Cc: Richard Henderson <rth@twiddle.net>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: "Hervé Poussineau" <hpoussin@reactos.org>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Reviewed-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Hervé Poussineau <hpoussin@reactos.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <1450370121-5768-11-git-send-email-armbru@redhat.com>
2015-12-18 00:35:18 +08:00
|
|
|
isa_bus = isa_bus_new(NULL, isa_mem, get_system_io(), &error_abort);
|
2015-02-01 16:12:53 +08:00
|
|
|
|
2007-04-08 02:14:41 +08:00
|
|
|
/* The PIC is attached to the MIPS CPU INT0 pin */
|
2011-12-16 05:09:51 +08:00
|
|
|
i8259 = i8259_init(isa_bus, env->irq[2]);
|
|
|
|
isa_bus_irqs(isa_bus, i8259);
|
2007-04-08 02:14:41 +08:00
|
|
|
|
2017-10-18 00:44:16 +08:00
|
|
|
mc146818_rtc_init(isa_bus, 2000, NULL);
|
2006-12-08 02:15:35 +08:00
|
|
|
|
2017-10-18 00:44:15 +08:00
|
|
|
pit = i8254_pit_init(isa_bus, 0x40, 0, NULL);
|
2006-12-08 02:15:35 +08:00
|
|
|
|
2018-04-20 22:52:46 +08:00
|
|
|
serial_hds_isa_init(isa_bus, 0, MAX_ISA_SERIAL_PORTS);
|
2006-12-23 08:23:19 +08:00
|
|
|
|
2012-09-08 23:02:29 +08:00
|
|
|
isa_vga_init(isa_bus);
|
2005-07-02 23:26:04 +08:00
|
|
|
|
2012-07-24 23:35:11 +08:00
|
|
|
if (nd_table[0].used)
|
2011-12-16 05:09:51 +08:00
|
|
|
isa_ne2000_init(isa_bus, 0x300, 9, &nd_table[0]);
|
2006-10-29 23:38:28 +08:00
|
|
|
|
2014-10-02 02:19:27 +08:00
|
|
|
ide_drive_get(hd, ARRAY_SIZE(hd));
|
2007-12-02 12:51:10 +08:00
|
|
|
for(i = 0; i < MAX_IDE_BUS; i++)
|
2011-12-16 05:09:51 +08:00
|
|
|
isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i],
|
2007-12-02 12:51:10 +08:00
|
|
|
hd[MAX_IDE_DEVS * i],
|
2018-12-14 06:37:37 +08:00
|
|
|
hd[MAX_IDE_DEVS * i + 1]);
|
2007-02-18 08:10:59 +08:00
|
|
|
|
2018-03-09 06:39:24 +08:00
|
|
|
isa_create_simple(isa_bus, TYPE_I8042);
|
2005-07-02 22:58:51 +08:00
|
|
|
}
|
|
|
|
|
2015-09-05 02:37:08 +08:00
|
|
|
static void mips_machine_init(MachineClass *mc)
|
2009-05-21 07:38:09 +08:00
|
|
|
{
|
2015-09-05 02:37:08 +08:00
|
|
|
mc->desc = "mips r4k platform";
|
|
|
|
mc->init = mips_r4k_init;
|
2017-02-15 18:05:40 +08:00
|
|
|
mc->block_default_type = IF_IDE;
|
2017-10-05 21:51:14 +08:00
|
|
|
#ifdef TARGET_MIPS64
|
|
|
|
mc->default_cpu_type = MIPS_CPU_TYPE_NAME("R4000");
|
|
|
|
#else
|
|
|
|
mc->default_cpu_type = MIPS_CPU_TYPE_NAME("24Kf");
|
|
|
|
#endif
|
|
|
|
|
2009-05-21 07:38:09 +08:00
|
|
|
}
|
|
|
|
|
2015-09-05 02:37:08 +08:00
|
|
|
DEFINE_MACHINE("mips", mips_machine_init)
|