obj-ppc-$(CONFIG_FDT) += device_tree.o
obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
-obj-mips-y += mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o rc4030.o
+obj-mips-y += mips_addr.o mips_timer.o mips_int.o
+obj-mips-y += dma.o vga.o serial.o i8254.o i8259.o rc4030.o
obj-mips-y += vga-pci.o vga-isa.o vga-isa-mm.o
obj-mips-y += g364fb.o jazz_led.o dp8393x.o
obj-mips-y += ide/core.o ide/qdev.o ide/isa.o ide/pci.o ide/piix.o
exit(1);
}
- kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL,
- 1, ELF_MACHINE, 0);
+ kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ NULL, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
#endif
/* Assume that raw images are linux kernels, and ELF images are not. */
- kernel_size = load_elf(info->kernel_filename, 0, &elf_entry, NULL, NULL,
- big_endian, ELF_MACHINE, 1);
+ kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
+ NULL, NULL, big_endian, ELF_MACHINE, 1);
entry = elf_entry;
if (kernel_size < 0) {
kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
big_endian = 0;
#endif
- image_size = load_elf(kernel_filename, 0, &entry, &lowaddr, NULL,
- big_endian, ELF_MACHINE, 1);
+ image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
+ NULL, big_endian, ELF_MACHINE, 1);
if (image_size < 0) {
image_size = load_image_targphys(kernel_filename, 0, flash_size);
lowaddr = 0;
env->pc = bootstrap_pc;
}
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+ return addr - 0x80000000LL;
+}
+
static
void axisdev88_init (ram_addr_t ram_size,
const char *boot_device,
/* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis
devboard SDK. */
- kernel_size = load_elf(kernel_filename, -0x80000000LL,
+ kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
&entry, NULL, &high, 0, ELF_MACHINE, 0);
bootstrap_pc = entry;
if (kernel_size < 0) {
/* Load kernel. */
if (kernel_filename) {
- kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL,
- 1, ELF_MACHINE, 0);
+ kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ NULL, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
return -1;
}
-static int glue(load_elf, SZ)(const char *name, int fd, int64_t address_offset,
+static int glue(load_elf, SZ)(const char *name, int fd,
+ uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque,
int must_swab, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr,
int elf_machine, int clear_lsb)
}
/* address_offset is hack for kernel images that are
linked at the wrong physical address. */
- addr = ph->p_paddr + address_offset;
+ if (translate_fn) {
+ addr = translate_fn(translate_opaque, ph->p_paddr);
+ } else {
+ addr = ph->p_paddr;
+ }
snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
rom_add_blob_fixed(label, data, mem_size, addr);
env->pc = bootstrap_pc;
}
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+ return addr - 0x80000000LL;
+}
+
static
void bareetraxfs_init (ram_addr_t ram_size,
const char *boot_device,
/* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis
devboard SDK. */
- kernel_size = load_elf(kernel_filename, -0x80000000LL,
+ kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
&entry, NULL, &high, 0, ELF_MACHINE, 0);
bootstrap_pc = entry;
if (kernel_size < 0) {
#include "elf_ops.h"
/* return < 0 if error, otherwise the number of bytes loaded in memory */
-int load_elf(const char *filename, int64_t address_offset,
- uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr,
- int big_endian, int elf_machine, int clear_lsb)
+int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
+ uint64_t *highaddr, int big_endian, int elf_machine, int clear_lsb)
{
int fd, data_order, target_data_order, must_swab, ret;
uint8_t e_ident[EI_NIDENT];
lseek(fd, 0, SEEK_SET);
if (e_ident[EI_CLASS] == ELFCLASS64) {
- ret = load_elf64(filename, fd, address_offset, must_swab, pentry,
- lowaddr, highaddr, elf_machine, clear_lsb);
+ ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab,
+ pentry, lowaddr, highaddr, elf_machine, clear_lsb);
} else {
- ret = load_elf32(filename, fd, address_offset, must_swab, pentry,
- lowaddr, highaddr, elf_machine, clear_lsb);
+ ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab,
+ pentry, lowaddr, highaddr, elf_machine, clear_lsb);
}
close(fd);
int get_image_size(const char *filename);
int load_image(const char *filename, uint8_t *addr); /* deprecated */
int load_image_targphys(const char *filename, target_phys_addr_t, int max_sz);
-int load_elf(const char *filename, int64_t address_offset,
- uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr,
- int big_endian, int elf_machine, int clear_lsb);
+int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
+ uint64_t *highaddr, int big_endian, int elf_machine,
+ int clear_lsb);
int load_aout(const char *filename, target_phys_addr_t addr, int max_sz,
int bswap_needed, target_phys_addr_t target_page_size);
int load_uimage(const char *filename, target_phys_addr_t *ep,
exit(1);
}
- kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL,
- 1, ELF_MACHINE, 0);
+ kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ NULL, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
/* jazz_led.c */
extern void jazz_led_init(target_phys_addr_t base);
+/* mips_addr.c */
+uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr);
+uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr);
+
/* mips_int.c */
extern void cpu_mips_irq_init_cpu(CPUState *env);
--- /dev/null
+/*
+ * QEMU MIPS address translation support
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw.h"
+#include "mips.h"
+
+uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr)
+{
+ return addr & 0x7fffffffll;
+}
+
+uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr)
+{
+ return addr | ~0x7fffffffll;
+}
//#define DEBUG_BOARD_INIT
-#ifdef TARGET_MIPS64
-#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
-#else
-#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
-#endif
-
-#define ENVP_ADDR (int32_t)0x80002000
-#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
-
+#define ENVP_ADDR 0x80002000l
#define ENVP_NB_ENTRIES 16
#define ENVP_ENTRY_SIZE 256
/* Kernel */
static int64_t load_kernel (void)
{
- int64_t kernel_entry, kernel_low, kernel_high;
+ int64_t kernel_entry, kernel_high;
long initrd_size;
ram_addr_t initrd_offset;
int big_endian;
big_endian = 0;
#endif
- if (load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
- (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
- (uint64_t *)&kernel_high, big_endian, ELF_MACHINE, 1) < 0) {
+ if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
+ (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
+ big_endian, ELF_MACHINE, 1) < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
loaderparams.kernel_filename);
exit(1);
prom_set(prom_buf, prom_index++, loaderparams.kernel_filename);
if (initrd_size > 0) {
- prom_set(prom_buf, prom_index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
- PHYS_TO_VIRT(initrd_offset), initrd_size,
+ prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
+ cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
loaderparams.kernel_cmdline);
} else {
prom_set(prom_buf, prom_index++, loaderparams.kernel_cmdline);
prom_set(prom_buf, prom_index++, NULL);
rom_add_blob_fixed("prom", prom_buf, prom_size,
- ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
+ cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
return kernel_entry;
}
#include "loader.h"
#include "elf.h"
-#ifdef TARGET_MIPS64
-#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
-#else
-#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
-#endif
-
-#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
-
static struct _loaderparams {
int ram_size;
const char *kernel_filename;
static int64_t load_kernel(void)
{
- int64_t entry, kernel_low, kernel_high;
+ int64_t entry, kernel_high;
long kernel_size;
long initrd_size;
ram_addr_t initrd_offset;
big_endian = 0;
#endif
- kernel_size = load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
- (uint64_t *)&entry, (uint64_t *)&kernel_low,
- (uint64_t *)&kernel_high, big_endian, ELF_MACHINE, 1);
+ kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
+ NULL, (uint64_t *)&entry, NULL,
+ (uint64_t *)&kernel_high, big_endian,
+ ELF_MACHINE, 1);
if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000)
entry = (int32_t)entry;
#include "loader.h"
#include "elf.h"
-#define PHYS_TO_VIRT(x) ((x) | ~(target_ulong)0x7fffffff)
-
-#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
-
#define MAX_IDE_BUS 2
static const int ide_iobase[2] = { 0x1f0, 0x170 };
static int64_t load_kernel(void)
{
- int64_t entry, kernel_low, kernel_high;
+ int64_t entry, kernel_high;
long kernel_size, initrd_size, params_size;
ram_addr_t initrd_offset;
uint32_t *params_buf;
#else
big_endian = 0;
#endif
- kernel_size = load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
- (uint64_t *)&entry, (uint64_t *)&kernel_low,
- (uint64_t *)&kernel_high, big_endian, ELF_MACHINE, 1);
+ kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
+ NULL, (uint64_t *)&entry, NULL,
+ (uint64_t *)&kernel_high, big_endian,
+ ELF_MACHINE, 1);
if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000)
entry = (int32_t)entry;
params_buf[1] = tswap32(0x12345678);
if (initrd_size > 0) {
- snprintf((char *)params_buf + 8, 256, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
- PHYS_TO_VIRT((uint32_t)initrd_offset),
+ 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);
uint64_t elf_low, elf_high;
int kernel_size;
fclose(f);
- kernel_size = load_elf(kernel_filename, 0, &elf_entry, &elf_low, &elf_high,
- 0, ELF_MACHINE, 0);
+ kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ &elf_low, &elf_high, 0, ELF_MACHINE, 0);
if (kernel_size < 0) {
fprintf(stderr, "Error while loading elf kernel\n");
exit(1);
return fdt_size;
}
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+ return addr - 0x30000000LL;
+}
+
static void
petalogix_s3adsp1800_init(ram_addr_t ram_size,
const char *boot_device,
uint32_t base32;
/* Boots a kernel elf binary. */
- kernel_size = load_elf(kernel_filename, 0,
+ kernel_size = load_elf(kernel_filename, NULL, NULL,
&entry, &low, &high,
1, ELF_MACHINE, 0);
base32 = entry;
if (base32 == 0xc0000000) {
- kernel_size = load_elf(kernel_filename, -0x30000000LL,
- &entry, NULL, NULL,
+ kernel_size = load_elf(kernel_filename, translate_kernel_address,
+ NULL, &entry, NULL, NULL,
1, ELF_MACHINE, 0);
}
/* Always boot into physical ram. */
if (kernel_filename) {
kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
if (kernel_size < 0) {
- kernel_size = load_elf(kernel_filename, 0, &elf_entry, &elf_lowaddr,
- NULL, 1, ELF_MACHINE, 0);
+ kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
loadaddr = elf_lowaddr;
}
return 0;
}
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+ return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
+}
+
/* PowerPC Mac99 hardware initialisation */
static void ppc_core99_init (ram_addr_t ram_size,
const char *boot_device,
/* Load OpenBIOS (ELF) */
if (filename) {
- bios_size = load_elf(filename, 0, NULL, NULL, NULL, 1, ELF_MACHINE, 0);
+ bios_size = load_elf(filename, NULL, NULL, NULL,
+ NULL, NULL, 1, ELF_MACHINE, 0);
qemu_free(filename);
} else {
#endif
kernel_base = KERNEL_LOAD_ADDR;
- /* Now we can load the kernel. The first step tries to load the kernel
- supposing PhysAddr = 0x00000000. If that was wrong the kernel is
- loaded again, the new PhysAddr being computed from lowaddr. */
- kernel_size = load_elf(kernel_filename, kernel_base, NULL, &lowaddr, NULL,
- 1, ELF_MACHINE, 0);
- if (kernel_size > 0 && lowaddr != KERNEL_LOAD_ADDR) {
- kernel_size = load_elf(kernel_filename, (2 * kernel_base) - lowaddr,
- NULL, NULL, NULL, 1, ELF_MACHINE, 0);
- }
+ kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+ NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, kernel_base,
ram_size - kernel_base, bswap_needed,
return 0;
}
+
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+ return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
+}
+
static void ppc_heathrow_init (ram_addr_t ram_size,
const char *boot_device,
const char *kernel_filename,
/* Load OpenBIOS (ELF) */
if (filename) {
- bios_size = load_elf(filename, 0, NULL, NULL, NULL,
- 1, ELF_MACHINE, 0);
+ bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL,
+ 1, ELF_MACHINE, 0);
qemu_free(filename);
} else {
bios_size = -1;
bswap_needed = 0;
#endif
kernel_base = KERNEL_LOAD_ADDR;
- /* Now we can load the kernel. The first step tries to load the kernel
- supposing PhysAddr = 0x00000000. If that was wrong the kernel is
- loaded again, the new PhysAddr being computed from lowaddr. */
- kernel_size = load_elf(kernel_filename, kernel_base, NULL, &lowaddr, NULL,
- 1, ELF_MACHINE, 0);
- if (kernel_size > 0 && lowaddr != KERNEL_LOAD_ADDR) {
- kernel_size = load_elf(kernel_filename, (2 * kernel_base) - lowaddr,
- NULL, NULL, NULL, 1, ELF_MACHINE, 0);
- }
+ kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+ NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, kernel_base,
ram_size - kernel_base, bswap_needed,
if (kernel_filename) {
kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
if (kernel_size < 0) {
- kernel_size = load_elf(kernel_filename, 0, &elf_entry, &elf_lowaddr,
- NULL, 1, ELF_MACHINE, 0);
+ kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
loadaddr = elf_lowaddr;
}
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
}
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+ return addr - 0xf0000000ULL;
+}
+
static unsigned long sun4m_load_kernel(const char *kernel_filename,
const char *initrd_filename,
ram_addr_t RAM_size)
#else
bswap_needed = 0;
#endif
- kernel_size = load_elf(kernel_filename, -0xf0000000ULL, NULL, NULL,
- NULL, 1, ELF_MACHINE, 0);
+ kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+ NULL, NULL, NULL, 1, ELF_MACHINE, 0);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
device_init(afx_register_devices);
/* Boot PROM (OpenBIOS) */
+static uint64_t translate_prom_address(void *opaque, uint64_t addr)
+{
+ target_phys_addr_t *base_addr = (target_phys_addr_t *)opaque;
+ return addr + *base_addr - PROM_VADDR;
+}
+
static void prom_init(target_phys_addr_t addr, const char *bios_name)
{
DeviceState *dev;
}
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) {
- ret = load_elf(filename, addr - PROM_VADDR, NULL, NULL, NULL,
- 1, ELF_MACHINE, 0);
+ ret = load_elf(filename, translate_prom_address, &addr, NULL,
+ NULL, NULL, 1, ELF_MACHINE, 0);
if (ret < 0 || ret > PROM_SIZE_MAX) {
ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
}
#else
bswap_needed = 0;
#endif
- kernel_size = load_elf(kernel_filename, 0, NULL, NULL, NULL,
- 1, ELF_MACHINE, 0);
+ kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
+ NULL, NULL, 1, ELF_MACHINE, 0);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
device_init(pci_ebus_register);
+static uint64_t translate_prom_address(void *opaque, uint64_t addr)
+{
+ target_phys_addr_t *base_addr = (target_phys_addr_t *)opaque;
+ return addr + *base_addr - PROM_VADDR;
+}
+
/* Boot PROM (OpenBIOS) */
static void prom_init(target_phys_addr_t addr, const char *bios_name)
{
}
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) {
- ret = load_elf(filename, addr - PROM_VADDR, NULL, NULL, NULL,
- 1, ELF_MACHINE, 0);
+ ret = load_elf(filename, translate_prom_address, &addr,
+ NULL, NULL, NULL, 1, ELF_MACHINE, 0);
if (ret < 0 || ret > PROM_SIZE_MAX) {
ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
}