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

microblaze: Add PetaLogix ml605 MMU little-endian ref design

Add the first Microblaze little endian platform.
Platform uses uart16550, axi ethernet, timer, intc.

Signed-off-by: Michal Simek <monstr@monstr.eu>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@petalogix.com>

authored by

Michal Simek and committed by
Edgar E. Iglesias
00914b7d 93f1e401

+308 -1
+1 -1
Makefile
··· 211 211 pxe-e1000.bin \ 212 212 pxe-ne2k_pci.bin pxe-pcnet.bin \ 213 213 pxe-rtl8139.bin pxe-virtio.bin \ 214 - bamboo.dtb petalogix-s3adsp1800.dtb \ 214 + bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \ 215 215 multiboot.bin linuxboot.bin \ 216 216 s390-zipl.rom 217 217 else
+1
Makefile.target
··· 266 266 obj-mips-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o 267 267 268 268 obj-microblaze-y = petalogix_s3adsp1800_mmu.o 269 + obj-microblaze-y += petalogix_ml605_mmu.o 269 270 270 271 obj-microblaze-y += microblaze_pic_cpu.o 271 272 obj-microblaze-y += xilinx_intc.o
+267
hw/petalogix_ml605_mmu.c
··· 1 + /* 2 + * Model of Petalogix linux reference design targeting Xilinx Spartan ml605 3 + * board. 4 + * 5 + * Copyright (c) 2011 Michal Simek <monstr@monstr.eu> 6 + * Copyright (c) 2011 PetaLogix 7 + * Copyright (c) 2009 Edgar E. Iglesias. 8 + * 9 + * Permission is hereby granted, free of charge, to any person obtaining a copy 10 + * of this software and associated documentation files (the "Software"), to deal 11 + * in the Software without restriction, including without limitation the rights 12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 + * copies of the Software, and to permit persons to whom the Software is 14 + * furnished to do so, subject to the following conditions: 15 + * 16 + * The above copyright notice and this permission notice shall be included in 17 + * all copies or substantial portions of the Software. 18 + * 19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 + * THE SOFTWARE. 26 + */ 27 + 28 + #include "sysbus.h" 29 + #include "hw.h" 30 + #include "net.h" 31 + #include "flash.h" 32 + #include "sysemu.h" 33 + #include "devices.h" 34 + #include "boards.h" 35 + #include "device_tree.h" 36 + #include "xilinx.h" 37 + #include "loader.h" 38 + #include "elf.h" 39 + #include "blockdev.h" 40 + #include "pc.h" 41 + 42 + #include "xilinx_axidma.h" 43 + 44 + #define LMB_BRAM_SIZE (128 * 1024) 45 + #define FLASH_SIZE (32 * 1024 * 1024) 46 + 47 + static struct 48 + { 49 + uint32_t bootstrap_pc; 50 + uint32_t cmdline; 51 + uint32_t fdt; 52 + } boot_info; 53 + 54 + static void main_cpu_reset(void *opaque) 55 + { 56 + CPUState *env = opaque; 57 + 58 + cpu_reset(env); 59 + env->regs[5] = boot_info.cmdline; 60 + env->regs[7] = boot_info.fdt; 61 + env->sregs[SR_PC] = boot_info.bootstrap_pc; 62 + env->pvr.regs[10] = 0x0e000000; /* virtex 6 */ 63 + /* setup pvr to match kernel setting */ 64 + env->pvr.regs[5] |= PVR5_DCACHE_WRITEBACK_MASK; 65 + env->pvr.regs[0] |= PVR0_USE_FPU_MASK | PVR0_ENDI; 66 + env->pvr.regs[0] = (env->pvr.regs[0] & ~PVR0_VERSION_MASK) | (0x14 << 8); 67 + env->pvr.regs[2] ^= PVR2_USE_FPU2_MASK; 68 + env->pvr.regs[4] = 0xc56b8000; 69 + env->pvr.regs[5] = 0xc56be000; 70 + } 71 + 72 + #define BINARY_DEVICE_TREE_FILE "petalogix-ml605.dtb" 73 + static int petalogix_load_device_tree(target_phys_addr_t addr, 74 + uint32_t ramsize, 75 + target_phys_addr_t initrd_base, 76 + target_phys_addr_t initrd_size, 77 + const char *kernel_cmdline) 78 + { 79 + char *path; 80 + int fdt_size; 81 + #ifdef CONFIG_FDT 82 + void *fdt; 83 + int r; 84 + 85 + /* Try the local "mb.dtb" override. */ 86 + fdt = load_device_tree("mb.dtb", &fdt_size); 87 + if (!fdt) { 88 + path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); 89 + if (path) { 90 + fdt = load_device_tree(path, &fdt_size); 91 + qemu_free(path); 92 + } 93 + if (!fdt) { 94 + return 0; 95 + } 96 + } 97 + 98 + r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline); 99 + if (r < 0) { 100 + fprintf(stderr, "couldn't set /chosen/bootargs\n"); 101 + } 102 + cpu_physical_memory_write(addr, (void *)fdt, fdt_size); 103 + #else 104 + /* We lack libfdt so we cannot manipulate the fdt. Just pass on the blob 105 + to the kernel. */ 106 + fdt_size = load_image_targphys("mb.dtb", addr, 0x10000); 107 + if (fdt_size < 0) { 108 + path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); 109 + if (path) { 110 + fdt_size = load_image_targphys(path, addr, 0x10000); 111 + qemu_free(path); 112 + } 113 + } 114 + 115 + if (kernel_cmdline) { 116 + fprintf(stderr, 117 + "Warning: missing libfdt, cannot pass cmdline to kernel!\n"); 118 + } 119 + #endif 120 + return fdt_size; 121 + } 122 + 123 + static uint64_t translate_kernel_address(void *opaque, uint64_t addr) 124 + { 125 + return addr - 0x30000000LL; 126 + } 127 + 128 + #define MEMORY_BASEADDR 0x50000000 129 + #define FLASH_BASEADDR 0x86000000 130 + #define INTC_BASEADDR 0x81800000 131 + #define TIMER_BASEADDR 0x83c00000 132 + #define UART16550_BASEADDR 0x83e00000 133 + #define AXIENET_BASEADDR 0x82780000 134 + #define AXIDMA_BASEADDR 0x84600000 135 + 136 + static void 137 + petalogix_ml605_init(ram_addr_t ram_size, 138 + const char *boot_device, 139 + const char *kernel_filename, 140 + const char *kernel_cmdline, 141 + const char *initrd_filename, const char *cpu_model) 142 + { 143 + DeviceState *dev; 144 + CPUState *env; 145 + int kernel_size; 146 + DriveInfo *dinfo; 147 + int i; 148 + target_phys_addr_t ddr_base = MEMORY_BASEADDR; 149 + ram_addr_t phys_lmb_bram; 150 + ram_addr_t phys_ram; 151 + ram_addr_t phys_flash; 152 + qemu_irq irq[32], *cpu_irq; 153 + void *serial = NULL; 154 + 155 + /* init CPUs */ 156 + if (cpu_model == NULL) { 157 + cpu_model = "microblaze"; 158 + } 159 + env = cpu_init(cpu_model); 160 + 161 + qemu_register_reset(main_cpu_reset, env); 162 + 163 + /* Attach emulated BRAM through the LMB. */ 164 + phys_lmb_bram = qemu_ram_alloc(NULL, "petalogix_ml605.lmb_bram", 165 + LMB_BRAM_SIZE); 166 + cpu_register_physical_memory(0x00000000, LMB_BRAM_SIZE, 167 + phys_lmb_bram | IO_MEM_RAM); 168 + 169 + phys_ram = qemu_ram_alloc(NULL, "petalogix_ml605.ram", ram_size); 170 + cpu_register_physical_memory(ddr_base, ram_size, phys_ram | IO_MEM_RAM); 171 + 172 + phys_flash = qemu_ram_alloc(NULL, "petalogix_ml605.flash", FLASH_SIZE); 173 + dinfo = drive_get(IF_PFLASH, 0, 0); 174 + /* 5th parameter 2 means bank-width 175 + * 10th paremeter 0 means little-endian */ 176 + pflash_cfi01_register(FLASH_BASEADDR, phys_flash, 177 + dinfo ? dinfo->bdrv : NULL, (64 * 1024), 178 + FLASH_SIZE >> 16, 179 + 2, 0x89, 0x18, 0x0000, 0x0, 0); 180 + 181 + 182 + cpu_irq = microblaze_pic_init_cpu(env); 183 + dev = xilinx_intc_create(INTC_BASEADDR, cpu_irq[0], 4); 184 + for (i = 0; i < 32; i++) { 185 + irq[i] = qdev_get_gpio_in(dev, i); 186 + } 187 + 188 + serial = serial_mm_init(UART16550_BASEADDR + 0x1000, 2, irq[5], 189 + 115200, serial_hds[0], 1, 0); 190 + 191 + /* 2 timers at irq 2 @ 100 Mhz. */ 192 + xilinx_timer_create(TIMER_BASEADDR, irq[2], 2, 100 * 1000000); 193 + 194 + /* axi ethernet and dma initialization. TODO: Dynamically connect them. */ 195 + { 196 + static struct XilinxDMAConnection dmach; 197 + 198 + xilinx_axiethernet_create(&dmach, &nd_table[0], 0x82780000, 199 + irq[3], 0x1000, 0x1000); 200 + xilinx_axiethernetdma_create(&dmach, 0x84600000, 201 + irq[1], irq[0], 100 * 1000000); 202 + } 203 + 204 + if (kernel_filename) { 205 + uint64_t entry, low, high; 206 + uint32_t base32; 207 + int big_endian = 0; 208 + 209 + #ifdef TARGET_WORDS_BIGENDIAN 210 + big_endian = 1; 211 + #endif 212 + 213 + /* Boots a kernel elf binary. */ 214 + kernel_size = load_elf(kernel_filename, NULL, NULL, 215 + &entry, &low, &high, 216 + big_endian, ELF_MACHINE, 0); 217 + base32 = entry; 218 + if (base32 == 0xc0000000) { 219 + kernel_size = load_elf(kernel_filename, translate_kernel_address, 220 + NULL, &entry, NULL, NULL, 221 + big_endian, ELF_MACHINE, 0); 222 + } 223 + /* Always boot into physical ram. */ 224 + boot_info.bootstrap_pc = ddr_base + (entry & 0x0fffffff); 225 + 226 + /* If it wasn't an ELF image, try an u-boot image. */ 227 + if (kernel_size < 0) { 228 + target_phys_addr_t uentry, loadaddr; 229 + 230 + kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0); 231 + boot_info.bootstrap_pc = uentry; 232 + high = (loadaddr + kernel_size + 3) & ~3; 233 + } 234 + 235 + /* Not an ELF image nor an u-boot image, try a RAW image. */ 236 + if (kernel_size < 0) { 237 + kernel_size = load_image_targphys(kernel_filename, ddr_base, 238 + ram_size); 239 + boot_info.bootstrap_pc = ddr_base; 240 + high = (ddr_base + kernel_size + 3) & ~3; 241 + } 242 + 243 + boot_info.cmdline = high + 4096; 244 + if (kernel_cmdline && strlen(kernel_cmdline)) { 245 + pstrcpy_targphys("cmdline", boot_info.cmdline, 256, kernel_cmdline); 246 + } 247 + /* Provide a device-tree. */ 248 + boot_info.fdt = boot_info.cmdline + 4096; 249 + petalogix_load_device_tree(boot_info.fdt, ram_size, 250 + 0, 0, 251 + kernel_cmdline); 252 + } 253 + } 254 + 255 + static QEMUMachine petalogix_ml605_machine = { 256 + .name = "petalogix-ml605", 257 + .desc = "PetaLogix linux refdesign for xilinx ml605 little endian", 258 + .init = petalogix_ml605_init, 259 + .is_default = 0 260 + }; 261 + 262 + static void petalogix_ml605_machine_init(void) 263 + { 264 + qemu_register_machine(&petalogix_ml605_machine); 265 + } 266 + 267 + machine_init(petalogix_ml605_machine_init);
+39
hw/xilinx.h
··· 48 48 sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq); 49 49 return dev; 50 50 } 51 + 52 + static inline DeviceState * 53 + xilinx_axiethernet_create(void *dmach, 54 + NICInfo *nd, target_phys_addr_t base, qemu_irq irq, 55 + int txmem, int rxmem) 56 + { 57 + DeviceState *dev; 58 + qemu_check_nic_model(nd, "xilinx-axienet"); 59 + 60 + dev = qdev_create(NULL, "xilinx,axienet"); 61 + qdev_set_nic_properties(dev, nd); 62 + qdev_prop_set_uint32(dev, "c_rxmem", rxmem); 63 + qdev_prop_set_uint32(dev, "c_txmem", txmem); 64 + qdev_prop_set_ptr(dev, "dmach", dmach); 65 + qdev_init_nofail(dev); 66 + sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); 67 + sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq); 68 + 69 + return dev; 70 + } 71 + 72 + static inline DeviceState * 73 + xilinx_axiethernetdma_create(void *dmach, 74 + target_phys_addr_t base, qemu_irq irq, 75 + qemu_irq irq2, int freqhz) 76 + { 77 + DeviceState *dev = NULL; 78 + 79 + dev = qdev_create(NULL, "xilinx,axidma"); 80 + qdev_prop_set_uint32(dev, "freqhz", freqhz); 81 + qdev_prop_set_ptr(dev, "dmach", dmach); 82 + qdev_init_nofail(dev); 83 + 84 + sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); 85 + sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq2); 86 + sysbus_connect_irq(sysbus_from_qdev(dev), 1, irq); 87 + 88 + return dev; 89 + }
pc-bios/petalogix-ml605.dtb

This is a binary file and will not be displayed.