qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

Add generic Nios II board.

This patch adds support for a generic MMU-less Nios II board that can
be used e.g. for bare-metal compiler testing with the linker script
and startup code provided by libgloss. Nios II booting is also
tweaked so that bare-metal binaries start executing in RAM starting at
0x00000000, rather than an alias at 0xc0000000, which allows features
such as unwinding to work when binaries are linked to start at the
beginning of the address space.

The generic_nommu.c parts are based on code by Andrew Jenner, which was
in turn based on code by Marek Vasut.

Originally by Marek Vasut and Andrew Jenner.

Signed-off-by: Sandra Loosemore <sandra@codesourcery.com>
Signed-off-by: Julian Brown <julian@codesourcery.com>
Signed-off-by: Andrew Jenner <andrew@codesourcery.com>
Signed-off-by: Marek Vasut <marex@denx.de>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1554321185-2825-2-git-send-email-sandra@codesourcery.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

authored by

Sandra Loosemore and committed by
Peter Maydell
ed960ba9 e0fb2c3d

+123 -6
+1
default-configs/nios2-softmmu.mak
··· 3 3 # Boards: 4 4 # 5 5 CONFIG_NIOS2_10M50=y 6 + CONFIG_NIOS2_GENERIC_NOMMU=y
+4
hw/nios2/Kconfig
··· 4 4 select SERIAL 5 5 select ALTERA_TIMER 6 6 7 + config NIOS2_GENERIC_NOMMU 8 + bool 9 + select NIOS2 10 + 7 11 config NIOS2 8 12 bool
+1
hw/nios2/Makefile.objs
··· 1 1 obj-y = boot.o cpu_pic.o 2 2 obj-$(CONFIG_NIOS2_10M50) += 10m50_devboard.o 3 + obj-$(CONFIG_NIOS2_GENERIC_NOMMU) += generic_nommu.o
+12 -6
hw/nios2/boot.c
··· 138 138 if (kernel_filename) { 139 139 int kernel_size, fdt_size; 140 140 uint64_t entry, low, high; 141 - uint32_t base32; 142 141 int big_endian = 0; 143 142 144 143 #ifdef TARGET_WORDS_BIGENDIAN ··· 149 148 kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, 150 149 &entry, &low, &high, 151 150 big_endian, EM_ALTERA_NIOS2, 0, 0); 152 - base32 = entry; 153 - if (base32 == 0xc0000000) { 151 + if ((uint32_t)entry == 0xc0000000) { 152 + /* 153 + * The Nios II processor reference guide documents that the 154 + * kernel is placed at virtual memory address 0xc0000000, 155 + * and we've got something that points there. Reload it 156 + * and adjust the entry to get the address in physical RAM. 157 + */ 154 158 kernel_size = load_elf(kernel_filename, NULL, 155 159 translate_kernel_address, NULL, 156 160 &entry, NULL, NULL, 157 161 big_endian, EM_ALTERA_NIOS2, 0, 0); 162 + boot_info.bootstrap_pc = ddr_base + 0xc0000000 + 163 + (entry & 0x07ffffff); 164 + } else { 165 + /* Use the entry point in the ELF image. */ 166 + boot_info.bootstrap_pc = (uint32_t)entry; 158 167 } 159 - 160 - /* Always boot into physical ram. */ 161 - boot_info.bootstrap_pc = ddr_base + 0xc0000000 + (entry & 0x07ffffff); 162 168 163 169 /* If it wasn't an ELF image, try an u-boot image. */ 164 170 if (kernel_size < 0) {
+105
hw/nios2/generic_nommu.c
··· 1 + /* 2 + * Generic simulator target with no MMU or devices. This emulation is 3 + * compatible with the libgloss qemu-hosted.ld linker script for using 4 + * QEMU as an instruction set simulator. 5 + * 6 + * Copyright (c) 2018-2019 Mentor Graphics 7 + * 8 + * Copyright (c) 2016 Marek Vasut <marek.vasut@gmail.com> 9 + * 10 + * Based on LabX device code 11 + * 12 + * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com> 13 + * 14 + * This library is free software; you can redistribute it and/or 15 + * modify it under the terms of the GNU Lesser General Public 16 + * License as published by the Free Software Foundation; either 17 + * version 2.1 of the License, or (at your option) any later version. 18 + * 19 + * This library is distributed in the hope that it will be useful, 20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 + * Lesser General Public License for more details. 23 + * 24 + * You should have received a copy of the GNU Lesser General Public 25 + * License along with this library; if not, see 26 + * <http://www.gnu.org/licenses/lgpl-2.1.html> 27 + */ 28 + 29 + #include "qemu/osdep.h" 30 + #include "qapi/error.h" 31 + #include "qemu-common.h" 32 + #include "cpu.h" 33 + 34 + #include "hw/sysbus.h" 35 + #include "hw/hw.h" 36 + #include "hw/char/serial.h" 37 + #include "sysemu/sysemu.h" 38 + #include "hw/boards.h" 39 + #include "exec/memory.h" 40 + #include "exec/address-spaces.h" 41 + #include "qemu/config-file.h" 42 + 43 + #include "boot.h" 44 + 45 + #define BINARY_DEVICE_TREE_FILE "generic-nommu.dtb" 46 + 47 + static void nios2_generic_nommu_init(MachineState *machine) 48 + { 49 + Nios2CPU *cpu; 50 + MemoryRegion *address_space_mem = get_system_memory(); 51 + MemoryRegion *phys_tcm = g_new(MemoryRegion, 1); 52 + MemoryRegion *phys_tcm_alias = g_new(MemoryRegion, 1); 53 + MemoryRegion *phys_ram = g_new(MemoryRegion, 1); 54 + MemoryRegion *phys_ram_alias = g_new(MemoryRegion, 1); 55 + ram_addr_t tcm_base = 0x0; 56 + ram_addr_t tcm_size = 0x1000; /* 1 kiB, but QEMU limit is 4 kiB */ 57 + ram_addr_t ram_base = 0x10000000; 58 + ram_addr_t ram_size = 0x08000000; 59 + 60 + /* Physical TCM (tb_ram_1k) with alias at 0xc0000000 */ 61 + memory_region_init_ram(phys_tcm, NULL, "nios2.tcm", tcm_size, 62 + &error_abort); 63 + memory_region_init_alias(phys_tcm_alias, NULL, "nios2.tcm.alias", 64 + phys_tcm, 0, tcm_size); 65 + memory_region_add_subregion(address_space_mem, tcm_base, phys_tcm); 66 + memory_region_add_subregion(address_space_mem, 0xc0000000 + tcm_base, 67 + phys_tcm_alias); 68 + 69 + /* Physical DRAM with alias at 0xc0000000 */ 70 + memory_region_init_ram(phys_ram, NULL, "nios2.ram", ram_size, 71 + &error_abort); 72 + memory_region_init_alias(phys_ram_alias, NULL, "nios2.ram.alias", 73 + phys_ram, 0, ram_size); 74 + memory_region_add_subregion(address_space_mem, ram_base, phys_ram); 75 + memory_region_add_subregion(address_space_mem, 0xc0000000 + ram_base, 76 + phys_ram_alias); 77 + 78 + cpu = NIOS2_CPU(cpu_create(TYPE_NIOS2_CPU)); 79 + 80 + /* Remove MMU */ 81 + cpu->mmu_present = false; 82 + 83 + /* Reset vector is the first 32 bytes of RAM. */ 84 + cpu->reset_addr = ram_base; 85 + 86 + /* The interrupt vector comes right after reset. */ 87 + cpu->exception_addr = ram_base + 0x20; 88 + 89 + /* 90 + * The linker script does have a TLB miss memory region declared, 91 + * but this should never be used with no MMU. 92 + */ 93 + cpu->fast_tlb_miss_addr = 0x7fff400; 94 + 95 + nios2_load_kernel(cpu, ram_base, ram_size, machine->initrd_filename, 96 + BINARY_DEVICE_TREE_FILE, NULL); 97 + } 98 + 99 + static void nios2_generic_nommu_machine_init(struct MachineClass *mc) 100 + { 101 + mc->desc = "Generic NOMMU Nios II design"; 102 + mc->init = nios2_generic_nommu_init; 103 + } 104 + 105 + DEFINE_MACHINE("nios2-generic-nommu", nios2_generic_nommu_machine_init);