diff options
author | Björn Töpel <bjorn@kernel.org> | 2022-01-03 09:46:50 +0100 |
---|---|---|
committer | Daniel Lublin <daniel@lublin.se> | 2022-09-19 08:42:03 +0200 |
commit | dcd83196eb1a0eb65e8c58c3720420a7e9f54f48 (patch) | |
tree | 19d8dc00575cd84f1ccbb1b90f48599aa4ac93f4 | |
parent | 814a0505302d6af277557f10f88d3639eff7a547 (diff) | |
download | qemu-dcd83196eb1a0eb65e8c58c3720420a7e9f54f48.zip |
Make initial public release
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | configs/devices/riscv32-softmmu/default.mak | 1 | ||||
-rw-r--r-- | hw/riscv/Kconfig | 4 | ||||
-rw-r--r-- | hw/riscv/meson.build | 1 | ||||
-rw-r--r-- | hw/riscv/mta1_mkdf.c | 459 | ||||
-rw-r--r-- | include/hw/riscv/mta1_mkdf.h | 67 | ||||
-rw-r--r-- | include/hw/riscv/mta1_mkdf_mem.h | 109 | ||||
-rw-r--r-- | include/hw/riscv/mullvad_cpu.h | 26 | ||||
-rw-r--r-- | pc-bios/optionrom/Makefile | 1 | ||||
-rw-r--r-- | target/riscv/cpu.c | 9 | ||||
-rw-r--r-- | target/riscv/cpu.h | 1 |
12 files changed, 684 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore index eb2553026c..a24480c635 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ GTAGS *.depend_raw *.swp *.patch +.cache @@ -337,3 +337,8 @@ endif print-%: @echo '$*=$($*)' + + +.PHONY: update-mem-include +update-mem-include: + cp -af ../tillitis-key1/hw/application_fpga/fw/mta1_mkdf_mem.h include/hw/riscv/mta1_mkdf_mem.h diff --git a/configs/devices/riscv32-softmmu/default.mak b/configs/devices/riscv32-softmmu/default.mak index d847bd5692..9e6f0d0167 100644 --- a/configs/devices/riscv32-softmmu/default.mak +++ b/configs/devices/riscv32-softmmu/default.mak @@ -13,3 +13,4 @@ CONFIG_SIFIVE_E=y CONFIG_SIFIVE_U=y CONFIG_RISCV_VIRT=y CONFIG_OPENTITAN=y +CONFIG_MTA1_MKDF=y diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index d2d869aaad..ed68122a8b 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -17,6 +17,10 @@ config MICROCHIP_PFSOC select SIFIVE_PLIC select UNIMP +config MTA1_MKDF + bool + select UNIMP + config OPENTITAN bool select IBEX diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index ab6cae57ea..304ae03ac6 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -2,6 +2,7 @@ riscv_ss = ss.source_set() riscv_ss.add(files('boot.c'), fdt) riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: files('numa.c')) riscv_ss.add(files('riscv_hart.c')) +riscv_ss.add(when: 'CONFIG_MTA1_MKDF', if_true: files('mta1_mkdf.c')) riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c')) riscv_ss.add(when: 'CONFIG_RISCV_VIRT', if_true: files('virt.c')) riscv_ss.add(when: 'CONFIG_SHAKTI_C', if_true: files('shakti_c.c')) diff --git a/hw/riscv/mta1_mkdf.c b/hw/riscv/mta1_mkdf.c new file mode 100644 index 0000000000..fb5580a49c --- /dev/null +++ b/hw/riscv/mta1_mkdf.c @@ -0,0 +1,459 @@ +/* + * QEMU RISC-V Board Compatible with Mullvad MTA1-MKDF platform + * + * Copyright (c) 2022 Mullvad VPN AB + * + * Provides a board compatible with the Mullvad MTA1-MKDF platform: + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "qemu/cutils.h" +#include "hw/riscv/mta1_mkdf.h" +#include "qapi/error.h" +#include "hw/boards.h" +#include "hw/misc/unimp.h" +#include "hw/riscv/boot.h" +#include "qemu/units.h" +#include "sysemu/sysemu.h" +#include "hw/riscv/mullvad_cpu.h" +#include "hw/char/riscv_htif.h" +#include "qapi/qmp/qerror.h" +#include "qemu/log.h" + +static const MemMapEntry mta1_mkdf_memmap[] = { + // TODO js said that currently ROM size is 2048 W32, and max is 3072 W32 + // (8192 and 12288 bytes resp right). + [MTA1_MKDF_ROM] = { MTA1_MKDF_ROM_BASE, 0x20000 /*128K*/ }, + // js said that we will have 128 kByte RAM (2**15 W32). + [MTA1_MKDF_RAM] = { MTA1_MKDF_RAM_BASE, 0x20000 /*128K*/ }, + [MTA1_MKDF_MMIO] = { MTA1_MKDF_MMIO_BASE, MTA1_MKDF_MMIO_SIZE }, +}; + +static bool mta1_mkdf_setup_chardev(MTA1MKDFState *s, Error **errp) +{ + Chardev *chr; + + if (!s->fifo_chr_name) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + "fifo", "a valid character device"); + return false; + } + + chr = qemu_chr_find(s->fifo_chr_name); + if (!chr) { + error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, + "Device '%s' not found", s->fifo_chr_name); + return false; + } + + return qemu_chr_fe_init(&s->fifo_chr, chr, errp); +} + +static void mta1_mkdf_fifo_rx(void *opaque, const uint8_t *buf, int size) +{ + MTA1MKDFState *s = opaque; + + if (s->fifo_rx_len >= sizeof(s->fifo_rx)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: FIFO Rx dropped! size=%d\n", __func__, size); + return; + } + s->fifo_rx[s->fifo_rx_len++] = *buf; +} + +static int mta1_mkdf_fifo_can_rx(void *opaque) +{ + MTA1MKDFState *s = opaque; + + return s->fifo_rx_len < sizeof(s->fifo_rx); +} + +static void mta1_mkdf_fifo_event(void *opaque, QEMUChrEvent event) +{ +} + +static int mta1_mkdf_fifo_be_change(void *opaque) +{ + MTA1MKDFState *s = opaque; + + qemu_chr_fe_set_handlers(&s->fifo_chr, mta1_mkdf_fifo_can_rx, mta1_mkdf_fifo_rx, + mta1_mkdf_fifo_event, mta1_mkdf_fifo_be_change, s, + NULL, true); + + return 0; +} + + +static void mta1_mkdf_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) +{ + MTA1MKDFState *s = opaque; + uint8_t c = val; + const char *badmsg = ""; + + // add base to make absolute + addr += MTA1_MKDF_MMIO_BASE; + + if (addr == MTA1_MKDF_MMIO_QEMU_DEBUG) { + putchar(c); + return; + } + + // Check size + if (size != 4) { + badmsg = "size not 32 bits"; + goto bad; + } + // Check for alignment + if (addr % 4 != 0) { + badmsg = "addr not 32-bit aligned"; + goto bad; + } + + // Handle some read-only addresses first + if (addr >= MTA1_MKDF_MMIO_UDS_FIRST && addr <= MTA1_MKDF_MMIO_UDS_LAST) { + badmsg = "write to UDS"; + goto bad; + } + // TODO: temp UDA only has 1 address so it is only 1 word (4 bytes). Real + // has 4 addrs, so 4 words (16 bytes). + if (addr >= MTA1_MKDF_MMIO_QEMU_UDA && addr <= MTA1_MKDF_MMIO_QEMU_UDA) { + badmsg = "write to UDA"; + goto bad; + } + if (addr >= MTA1_MKDF_MMIO_MTA1_UDI_FIRST && addr <= MTA1_MKDF_MMIO_MTA1_UDI_LAST) { + badmsg = "write to UDI"; + goto bad; + } + + /* CDI u32[8] */ + if (addr >= MTA1_MKDF_MMIO_MTA1_CDI_FIRST && addr <= MTA1_MKDF_MMIO_MTA1_CDI_LAST) { + if (s->app_mode) { + badmsg = "write to CDI in app-mode"; + goto bad; + } + s->cdi[(addr - MTA1_MKDF_MMIO_MTA1_CDI_FIRST) / 4] = val; + return; + } + + badmsg = "addr/val/state not handled"; + + switch (addr) { + case MTA1_MKDF_MMIO_MTA1_SWITCH_APP: + if (s->app_mode) { + badmsg = "write to SWITCH_APP in app-mode"; + break; + } + s->app_mode = true; + return; + case MTA1_MKDF_MMIO_UART_TX_DATA: + qemu_chr_fe_write(&s->fifo_chr, &c, 1); + return; + case MTA1_MKDF_MMIO_MTA1_LED: + s->led = val; + qemu_log_mask(LOG_GUEST_ERROR, "%s: MTA1_LED rgb:%c%c%c\n", __func__, + val & MTA1_MKDF_MMIO_MTA1_LED_R_BIT ? '1' : '0', + val & MTA1_MKDF_MMIO_MTA1_LED_G_BIT ? '1' : '0', + val & MTA1_MKDF_MMIO_MTA1_LED_B_BIT ? '1' : '0'); + return; + case MTA1_MKDF_MMIO_TOUCH_STATUS: + // Always touched, we don't care about touch reset + return; + case MTA1_MKDF_MMIO_MTA1_APP_ADDR: + if (s->app_mode) { + badmsg = "write to APP_ADDR in app-mode"; + break; + } + s->app_addr = val; + return; + case MTA1_MKDF_MMIO_MTA1_APP_SIZE: + if (s->app_mode) { + badmsg = "write to APP_SIZE in app-mode"; + break; + } + s->app_size = val; + return; + } + +bad: + qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%x size=%d val=0x%x msg='%s'\n", + __func__, (int)addr, size, (int)val, badmsg); +} + +static uint64_t mta1_mkdf_mmio_read(void *opaque, hwaddr addr, unsigned size) +{ + MTA1MKDFState *s = opaque; + uint8_t r; + const char *badmsg = ""; + + // add base to make absolute + addr += MTA1_MKDF_MMIO_BASE; + + // Check size + if (size != 4) { + badmsg = "size not 32 bits"; + goto bad; + } + // Check for alignment + if (addr % 4 != 0) { + badmsg = "addr not 32-bit aligned"; + goto bad; + } + + /* UDS 32 bytes */ + if (addr >= MTA1_MKDF_MMIO_UDS_FIRST && addr <= MTA1_MKDF_MMIO_UDS_LAST) { + if (s->app_mode) { + badmsg = "read from UDS in app-mode"; + goto bad; + } + int i = (addr - MTA1_MKDF_MMIO_UDS_FIRST) / 4; + // Should only be read once + if (s->block_uds[i]) { + badmsg = "read from UDS twice"; + goto bad; + } + s->block_uds[i] = true; + return s->uds[i]; + } + + /* UDA 16 bytes */ + // TODO: temp UDA only has 1 address so it is only 1 word (4 bytes). Real + // has 4 addrs, so 4 words (16 bytes). + if (addr >= MTA1_MKDF_MMIO_QEMU_UDA && addr <= MTA1_MKDF_MMIO_QEMU_UDA) { + if (s->app_mode) { + badmsg = "read from UDA in app-mode"; + goto bad; + } + return s->uda[(addr - MTA1_MKDF_MMIO_QEMU_UDA) / 4]; + } + + /* CDI 32 bytes */ + if (addr >= MTA1_MKDF_MMIO_MTA1_CDI_FIRST && addr <= MTA1_MKDF_MMIO_MTA1_CDI_LAST) { + return s->cdi[(addr - MTA1_MKDF_MMIO_MTA1_CDI_FIRST) / 4]; + } + + /* UDI 8 bytes */ + if (addr >= MTA1_MKDF_MMIO_MTA1_UDI_FIRST && addr <= MTA1_MKDF_MMIO_MTA1_UDI_LAST) { + return s->udi[(addr - MTA1_MKDF_MMIO_MTA1_UDI_FIRST) / 4]; + } + + badmsg = "addr/val/state not handled"; + + switch (addr) { + case MTA1_MKDF_MMIO_MTA1_SWITCH_APP: + badmsg = "read from SWITCH_APP"; + break; + case MTA1_MKDF_MMIO_MTA1_NAME0: + return 0x6d746131; // "mta1" + case MTA1_MKDF_MMIO_MTA1_NAME1: + return 0x6d6b6466; // "mkdf" + case MTA1_MKDF_MMIO_MTA1_VERSION: + return 1; + case MTA1_MKDF_MMIO_UART_RX_STATUS: + return s->fifo_rx_len; + case MTA1_MKDF_MMIO_UART_RX_DATA: + if (s->fifo_rx_len) { + r = s->fifo_rx[0]; + memmove(s->fifo_rx, s->fifo_rx + 1, s->fifo_rx_len - 1); + s->fifo_rx_len--; + qemu_chr_fe_accept_input(&s->fifo_chr); + return r; + } + // TODO what is this returning?! + return 0x80000000; + case MTA1_MKDF_MMIO_UART_TX_STATUS: + return 1; + case MTA1_MKDF_MMIO_UART_TX_DATA: + badmsg = "read from TX_DATA"; + break; + case MTA1_MKDF_MMIO_MTA1_LED: + return s->led; + case MTA1_MKDF_MMIO_TIMER_TIMER: // u32 + break; + case MTA1_MKDF_MMIO_TRNG_STATUS: // u32 + break; + case MTA1_MKDF_MMIO_TRNG_ENTROPY: // u32 + break; + case MTA1_MKDF_MMIO_TOUCH_STATUS: + // Always touched + return 1 << MTA1_MKDF_MMIO_TOUCH_STATUS_EVENT_BIT; + case MTA1_MKDF_MMIO_MTA1_APP_ADDR: + return s->app_addr; + case MTA1_MKDF_MMIO_MTA1_APP_SIZE: + return s->app_size; + } + +bad: + qemu_log_mask(LOG_GUEST_ERROR, "%s: bad read: addr=0x%x size=%d msg='%s'\n", + __func__, (int)addr, size, badmsg); + return 0; +} + +static const MemoryRegionOps mta1_mkdf_mmio_ops = { + .read = mta1_mkdf_mmio_read, + .write = mta1_mkdf_mmio_write, + .endianness = DEVICE_LITTLE_ENDIAN, +#if 0 + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +#endif +}; + +static void mta1_mkdf_board_init(MachineState *machine) +{ + MachineClass *mc = MACHINE_GET_CLASS(machine); + MTA1MKDFState *s = MTA1_MKDF_MACHINE(machine); + const MemMapEntry *memmap = mta1_mkdf_memmap; + MemoryRegion *sys_mem = get_system_memory(); + Error *err = NULL; + + // Unique Device Secret + uint32_t uds[8] = { + 0x80808080, + 0x91919191, + 0xa2a2a2a2, + 0xb3b3b3b3, + 0xc4c4c4c4, + 0xd5d5d5d5, + 0xe6e6e6e6, + 0xf7f7f7f7 + }; + + memcpy(s->uds, uds, 32); + for (int i = 0; i < 8; i ++) { + s->block_uds[i] = false; + } + + // Unique Device Authentication key + for (int i = 0; i < 4; i ++) { + s->uda[i] = i+1; + } + + // Unique Device ID + for (int i = 0; i < 2; i ++) { + s->udi[i] = i+1; + } + + if (!mta1_mkdf_setup_chardev(s, &err)) { + error_report_err(err); + exit(EXIT_FAILURE); + } + + if (machine->ram_size != mc->default_ram_size) { + char *sz = size_to_str(mc->default_ram_size); + error_report("Invalid RAM size, should be %s.", sz); + g_free(sz); + exit(EXIT_FAILURE); + } + + if (strcmp(machine->cpu_type, TYPE_RISCV_CPU_MULLVAD_PICORV32) != 0) { + error_report("This board can only be used with a Mullvad PicoRV32 CPU"); + exit(EXIT_FAILURE); + } + + qemu_chr_fe_set_handlers(&s->fifo_chr, mta1_mkdf_fifo_can_rx, mta1_mkdf_fifo_rx, + mta1_mkdf_fifo_event, mta1_mkdf_fifo_be_change, s, + NULL, true); + + object_initialize_child(OBJECT(machine), "soc", &s->cpus, TYPE_RISCV_HART_ARRAY); + object_property_set_str(OBJECT(&s->cpus), "cpu-type", machine->cpu_type, &error_abort); + object_property_set_int(OBJECT(&s->cpus), "num-harts", machine->smp.cpus, &error_abort); + object_property_set_int(OBJECT(&s->cpus), "resetvec", memmap[MTA1_MKDF_ROM].base, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_abort); + + memory_region_init_rom(&s->rom, NULL, "riscv.mta1_mkdf.rom", memmap[MTA1_MKDF_ROM].size, &error_fatal); + memory_region_add_subregion(sys_mem, memmap[MTA1_MKDF_ROM].base, &s->rom); + + memory_region_add_subregion(sys_mem, memmap[MTA1_MKDF_RAM].base, machine->ram); + + memory_region_init_io(&s->mmio, OBJECT(s), &mta1_mkdf_mmio_ops, s, "riscv.mta1_mkdf.mmio", + memmap[MTA1_MKDF_MMIO].size); + memory_region_add_subregion(sys_mem, memmap[MTA1_MKDF_MMIO].base, &s->mmio); + // sysbus_init_mmio(sbd, &s->mmio); // XXX add to sysbusdevice? + + if (!machine->firmware) { + error_report("No firmware provided! Please use the -bios option."); + exit(EXIT_FAILURE); + } + + riscv_load_firmware(machine->firmware, memmap[MTA1_MKDF_ROM].base, htif_symbol_callback); + htif_mm_init(sys_mem, &s->rom, &s->cpus.harts[0].env, serial_hd(0)); +} + +static void mta1_mkdf_machine_instance_init(Object *obj) +{ +} + +static void mta1_mkdf_machine_set_chardev(Object *obj, + const char *value, Error **errp) +{ + MTA1MKDFState *s = MTA1_MKDF_MACHINE(obj); + + g_free(s->fifo_chr_name); + s->fifo_chr_name = g_strdup(value); +} + +static char * mta1_mkdf_machine_get_chardev(Object *obj, Error **errp) +{ + MTA1MKDFState *s = MTA1_MKDF_MACHINE(obj); + Chardev *chr = qemu_chr_fe_get_driver(&s->fifo_chr); + + if (chr && chr->label) { + return g_strdup(chr->label); + } + + return NULL; +} + +static void mta1_mkdf_machine_instance_finalize(Object *obj) +{ + MTA1MKDFState *s = MTA1_MKDF_MACHINE(obj); + + qemu_chr_fe_deinit(&s->fifo_chr, false); + g_free(s->fifo_chr_name); +} + +static void mta1_mkdf_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "Mullvad MTA1-MKDF Board"; + mc->init = mta1_mkdf_board_init; + mc->max_cpus = 1; + mc->default_cpu_type = MULLVAD_PICORV32_CPU; + mc->default_ram_id = "riscv.mta1_mkdf.ram"; + mc->default_ram_size = mta1_mkdf_memmap[MTA1_MKDF_RAM].size; + + object_class_property_add_str(oc, "fifo", + mta1_mkdf_machine_get_chardev, + mta1_mkdf_machine_set_chardev); + +} + +static const TypeInfo mta1_mkdf_machine_typeinfo = { + .name = TYPE_MTA1_MKDF_MACHINE, + .parent = TYPE_MACHINE, + .class_init = mta1_mkdf_machine_class_init, + .instance_init = mta1_mkdf_machine_instance_init, + .instance_size = sizeof(MTA1MKDFState), + .instance_finalize = mta1_mkdf_machine_instance_finalize, +}; + +static void mta1_mkdf_machine_init_register_types(void) +{ + type_register_static(&mta1_mkdf_machine_typeinfo); +} + +type_init(mta1_mkdf_machine_init_register_types) diff --git a/include/hw/riscv/mta1_mkdf.h b/include/hw/riscv/mta1_mkdf.h new file mode 100644 index 0000000000..d555792c7b --- /dev/null +++ b/include/hw/riscv/mta1_mkdf.h @@ -0,0 +1,67 @@ +/* + * QEMU RISC-V Board Compatible with Mullvad MTA1-MKDF platform + * + * Copyright (c) 2022 Mullvad VPN AB + * + * Provides a board compatible with the Mullvad MTA1-MKDF platform: + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef HW_MTA1_MKDF_H +#define HW_MTA1_MKDF_H + +#include "hw/boards.h" +#include "hw/riscv/riscv_hart.h" +#include "qom/object.h" +#include "chardev/char-fe.h" + +#include "hw/riscv/mta1_mkdf_mem.h" + +#define MTA1_MKDF_RX_FIFO_SIZE 16 + +typedef struct MTA1MKDFState { + /*< private >*/ + MachineState parent_obj; + + /*< public >*/ + RISCVHartArrayState cpus; + MemoryRegion rom; + MemoryRegion mmio; + + CharBackend fifo_chr; + char *fifo_chr_name; + uint8_t fifo_rx[MTA1_MKDF_RX_FIFO_SIZE]; + uint8_t fifo_rx_len; + bool app_mode; + uint32_t app_addr; + uint32_t app_size; + uint32_t uds[8]; // 32 bytes + bool block_uds[8]; + uint32_t uda[4]; // 16 bytes + uint32_t led; + uint32_t cdi[8]; // 32 bytes + uint32_t udi[2]; // 8 bytes +} MTA1MKDFState; + +#define TYPE_MTA1_MKDF_MACHINE MACHINE_TYPE_NAME("mta1_mkdf") +#define MTA1_MKDF_MACHINE(obj) \ + OBJECT_CHECK(MTA1MKDFState, (obj), TYPE_MTA1_MKDF_MACHINE) + +enum { + MTA1_MKDF_ROM, + MTA1_MKDF_RAM, + MTA1_MKDF_MMIO, +}; + +#endif diff --git a/include/hw/riscv/mta1_mkdf_mem.h b/include/hw/riscv/mta1_mkdf_mem.h new file mode 100644 index 0000000000..2a8b0c12ca --- /dev/null +++ b/include/hw/riscv/mta1_mkdf_mem.h @@ -0,0 +1,109 @@ +/* + * QEMU RISC-V Board Compatible with Mullvad MTA1-MKDF platform + * + * Copyright (c) 2022 Tillitis AB + * SPDX-License-Identifier: GPL-2.0-only + */ + +// clang-format off + +#ifndef HW_MTA1_MKDF_MEM_H +#define HW_MTA1_MKDF_MEM_H + +// The canonical location of this file is: +// repo: https://github.com/tillitis/tillitis-key1 +// path: /hw/application_fpga/fw/mta1_mkdf_mem.h + +// The contents are derived from the Verilog code. For use by QEMU model, +// firmware, and apps. + +enum { + MTA1_MKDF_ROM_BASE = 0x00000000, // 0b00000000... + MTA1_MKDF_RAM_BASE = 0x40000000, // 0b01000000... + MTA1_MKDF_RESERVED_BASE = 0x80000000, // 0b10000000... + MTA1_MKDF_MMIO_BASE = 0xc0000000, // 0b11000000... + MTA1_MKDF_MMIO_SIZE = 0xffffffff - MTA1_MKDF_MMIO_BASE, + + MTA1_MKDF_MMIO_TRNG_BASE = MTA1_MKDF_MMIO_BASE | 0x00000000, + MTA1_MKDF_MMIO_TIMER_BASE = MTA1_MKDF_MMIO_BASE | 0x01000000, + MTA1_MKDF_MMIO_UDS_BASE = MTA1_MKDF_MMIO_BASE | 0x02000000, + MTA1_MKDF_MMIO_UART_BASE = MTA1_MKDF_MMIO_BASE | 0x03000000, + MTA1_MKDF_MMIO_TOUCH_BASE = MTA1_MKDF_MMIO_BASE | 0x04000000, + // This "core" only exists in QEMU + MTA1_MKDF_MMIO_QEMU_BASE = MTA1_MKDF_MMIO_BASE | 0x3e000000, + MTA1_MKDF_MMIO_MTA1_BASE = MTA1_MKDF_MMIO_BASE | 0x3f000000, // 0xff000000 + + MTA1_MKDF_NAME0_SUFFIX = 0x00, + MTA1_MKDF_NAME1_SUFFIX = 0x04, + MTA1_MKDF_VERSION_SUFFIX = 0x08, + + MTA1_MKDF_MMIO_TRNG_NAME0 = MTA1_MKDF_MMIO_TRNG_BASE | MTA1_MKDF_NAME0_SUFFIX, + MTA1_MKDF_MMIO_TRNG_NAME1 = MTA1_MKDF_MMIO_TRNG_BASE | MTA1_MKDF_NAME1_SUFFIX, + MTA1_MKDF_MMIO_TRNG_VERSION = MTA1_MKDF_MMIO_TRNG_BASE | MTA1_MKDF_VERSION_SUFFIX, + MTA1_MKDF_MMIO_TRNG_STATUS = MTA1_MKDF_MMIO_TRNG_BASE | 0x24, + MTA1_MKDF_MMIO_TRNG_STATUS_READY_BIT = 0, + MTA1_MKDF_MMIO_TRNG_SAMPLE_RATE = MTA1_MKDF_MMIO_TRNG_BASE | 0x40, + MTA1_MKDF_MMIO_TRNG_ENTROPY = MTA1_MKDF_MMIO_TRNG_BASE | 0x80, + + MTA1_MKDF_MMIO_TIMER_NAME0 = MTA1_MKDF_MMIO_TIMER_BASE | MTA1_MKDF_NAME0_SUFFIX, + MTA1_MKDF_MMIO_TIMER_NAME1 = MTA1_MKDF_MMIO_TIMER_BASE | MTA1_MKDF_NAME1_SUFFIX, + MTA1_MKDF_MMIO_TIMER_VERSION = MTA1_MKDF_MMIO_TIMER_BASE | MTA1_MKDF_VERSION_SUFFIX, + MTA1_MKDF_MMIO_TIMER_CTRL = MTA1_MKDF_MMIO_TIMER_BASE | 0x20, + MTA1_MKDF_MMIO_TIMER_CTRL_START_BIT = 0, + MTA1_MKDF_MMIO_TIMER_CTRL_STOP_BIT = 1, + MTA1_MKDF_MMIO_TIMER_STATUS = MTA1_MKDF_MMIO_TIMER_BASE | 0x24, + MTA1_MKDF_MMIO_TIMER_STATUS_READY_BIT = 0, + MTA1_MKDF_MMIO_TIMER_PRESCALER = MTA1_MKDF_MMIO_TIMER_BASE | 0x28, + MTA1_MKDF_MMIO_TIMER_TIMER = MTA1_MKDF_MMIO_TIMER_BASE | 0x2c, + + MTA1_MKDF_MMIO_UDS_NAME0 = MTA1_MKDF_MMIO_UDS_BASE | MTA1_MKDF_NAME0_SUFFIX, + MTA1_MKDF_MMIO_UDS_NAME1 = MTA1_MKDF_MMIO_UDS_BASE | MTA1_MKDF_NAME1_SUFFIX, + MTA1_MKDF_MMIO_UDS_VERSION = MTA1_MKDF_MMIO_UDS_BASE | MTA1_MKDF_VERSION_SUFFIX, + MTA1_MKDF_MMIO_UDS_FIRST = MTA1_MKDF_MMIO_UDS_BASE | 0x40, + MTA1_MKDF_MMIO_UDS_LAST = MTA1_MKDF_MMIO_UDS_BASE | 0x5c, // Address of last 32-bit word of UDS + + MTA1_MKDF_MMIO_UART_NAME0 = MTA1_MKDF_MMIO_UART_BASE | MTA1_MKDF_NAME0_SUFFIX, + MTA1_MKDF_MMIO_UART_NAME1 = MTA1_MKDF_MMIO_UART_BASE | MTA1_MKDF_NAME1_SUFFIX, + MTA1_MKDF_MMIO_UART_VERSION = MTA1_MKDF_MMIO_UART_BASE | MTA1_MKDF_VERSION_SUFFIX, + MTA1_MKDF_MMIO_UART_BIT_RATE = MTA1_MKDF_MMIO_UART_BASE | 0x40, + MTA1_MKDF_MMIO_UART_DATA_BITS = MTA1_MKDF_MMIO_UART_BASE | 0x44, + MTA1_MKDF_MMIO_UART_STOP_BITS = MTA1_MKDF_MMIO_UART_BASE | 0x48, + MTA1_MKDF_MMIO_UART_RX_STATUS = MTA1_MKDF_MMIO_UART_BASE | 0x80, + MTA1_MKDF_MMIO_UART_RX_DATA = MTA1_MKDF_MMIO_UART_BASE | 0x84, + MTA1_MKDF_MMIO_UART_TX_STATUS = MTA1_MKDF_MMIO_UART_BASE | 0x100, + MTA1_MKDF_MMIO_UART_TX_DATA = MTA1_MKDF_MMIO_UART_BASE | 0x104, + + MTA1_MKDF_MMIO_TOUCH_NAME0 = MTA1_MKDF_MMIO_TOUCH_BASE | MTA1_MKDF_NAME0_SUFFIX, + MTA1_MKDF_MMIO_TOUCH_NAME1 = MTA1_MKDF_MMIO_TOUCH_BASE | MTA1_MKDF_NAME1_SUFFIX, + MTA1_MKDF_MMIO_TOUCH_VERSION = MTA1_MKDF_MMIO_TOUCH_BASE | MTA1_MKDF_VERSION_SUFFIX, + MTA1_MKDF_MMIO_TOUCH_STATUS = MTA1_MKDF_MMIO_TOUCH_BASE | 0x24, + MTA1_MKDF_MMIO_TOUCH_STATUS_EVENT_BIT = 0, + + // TODO HW core/addr is not yet defined for this: + MTA1_MKDF_MMIO_QEMU_UDA = MTA1_MKDF_MMIO_QEMU_BASE | 0x20, + // This will only ever exist in QEMU: + MTA1_MKDF_MMIO_QEMU_DEBUG = MTA1_MKDF_MMIO_QEMU_BASE | 0x1000, + + MTA1_MKDF_MMIO_MTA1_NAME0 = MTA1_MKDF_MMIO_MTA1_BASE | MTA1_MKDF_NAME0_SUFFIX, + MTA1_MKDF_MMIO_MTA1_NAME1 = MTA1_MKDF_MMIO_MTA1_BASE | MTA1_MKDF_NAME1_SUFFIX, + MTA1_MKDF_MMIO_MTA1_VERSION = MTA1_MKDF_MMIO_MTA1_BASE | MTA1_MKDF_VERSION_SUFFIX, + MTA1_MKDF_MMIO_MTA1_SWITCH_APP = MTA1_MKDF_MMIO_MTA1_BASE | 0x20, + MTA1_MKDF_MMIO_MTA1_LED = MTA1_MKDF_MMIO_MTA1_BASE | 0x24, + MTA1_MKDF_MMIO_MTA1_LED_R_BIT = 2, + MTA1_MKDF_MMIO_MTA1_LED_G_BIT = 1, + MTA1_MKDF_MMIO_MTA1_LED_B_BIT = 0, + MTA1_MKDF_MMIO_MTA1_GPIO = MTA1_MKDF_MMIO_MTA1_BASE | 0x28, + MTA1_MKDF_MMIO_MTA1_GPIO1_BIT = 0, + MTA1_MKDF_MMIO_MTA1_GPIO2_BIT = 1, + MTA1_MKDF_MMIO_MTA1_GPIO3_BIT = 2, + MTA1_MKDF_MMIO_MTA1_GPIO4_BIT = 3, + MTA1_MKDF_MMIO_MTA1_APP_ADDR = MTA1_MKDF_MMIO_MTA1_BASE | 0x30, // 0x4000_0000 + MTA1_MKDF_MMIO_MTA1_APP_SIZE = MTA1_MKDF_MMIO_MTA1_BASE | 0x34, + MTA1_MKDF_MMIO_MTA1_DEBUG = MTA1_MKDF_MMIO_MTA1_BASE | 0x40, + MTA1_MKDF_MMIO_MTA1_CDI_FIRST = MTA1_MKDF_MMIO_MTA1_BASE | 0x80, + MTA1_MKDF_MMIO_MTA1_CDI_LAST = MTA1_MKDF_MMIO_MTA1_BASE | 0x9c, // Address of last 32-bit word of CDI. + MTA1_MKDF_MMIO_MTA1_UDI_FIRST = MTA1_MKDF_MMIO_MTA1_BASE | 0xc0, + MTA1_MKDF_MMIO_MTA1_UDI_LAST = MTA1_MKDF_MMIO_MTA1_BASE | 0xc4, // Address of last 32-bit word of UDI. +}; + +#endif diff --git a/include/hw/riscv/mullvad_cpu.h b/include/hw/riscv/mullvad_cpu.h new file mode 100644 index 0000000000..01fb03c39e --- /dev/null +++ b/include/hw/riscv/mullvad_cpu.h @@ -0,0 +1,26 @@ +/* + * Mullvad CPU types + * + * Copyright (c) 2022 Mullvad VPN AB + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef HW_MULLVAD_CPU_H +#define HW_MULLVAD_CPU_H + +#if defined(TARGET_RISCV32) +#define MULLVAD_PICORV32_CPU TYPE_RISCV_CPU_MULLVAD_PICORV32 +#endif + +#endif /* HW_SIFIVE_CPU_H */ diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile index 5d55d25acc..c5f5fa02ef 100644 --- a/pc-bios/optionrom/Makefile +++ b/pc-bios/optionrom/Makefile @@ -21,6 +21,7 @@ override CFLAGS += $(filter -W%, $(QEMU_CFLAGS)) override CFLAGS += $(CFLAGS_NOPIE) -ffreestanding -I$(TOPSRC_DIR)/include override CFLAGS += $(call cc-option, -fno-stack-protector) override CFLAGS += $(call cc-option, -m16) +override CFLAGS += $(call cc-option, -fcf-protection=none) ifeq ($(filter -m16, $(CFLAGS)),) # Attempt to work around compilers that lack -m16 (GCC <= 4.8, clang <= ??) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 6ef3314bce..31065ab9ad 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -209,6 +209,14 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj) set_resetvec(env, DEFAULT_RSTVEC); qdev_prop_set_bit(DEVICE(obj), "mmu", false); } + +static void rv32_mullvad_picorv32_cpu_init(Object *obj) +{ + CPURISCVState *env = &RISCV_CPU(obj)->env; + set_misa(env, MXL_RV32, RVI | RVM | RVC); + qdev_prop_set_bit(DEVICE(obj), "mmu", false); + qdev_prop_set_bit(DEVICE(obj), "pmp", false); +} #endif static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model) @@ -812,6 +820,7 @@ static const TypeInfo riscv_cpu_type_infos[] = { DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32_sifive_e_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34, rv32_imafcu_nommu_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32_sifive_u_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_MULLVAD_PICORV32, rv32_mullvad_picorv32_cpu_init), #elif defined(TARGET_RISCV64) DEFINE_CPU(TYPE_RISCV_CPU_BASE64, rv64_base_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rv64_sifive_e_cpu_init), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index dc10f27093..ef725d5be0 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -45,6 +45,7 @@ #define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51") #define TYPE_RISCV_CPU_SIFIVE_U34 RISCV_CPU_TYPE_NAME("sifive-u34") #define TYPE_RISCV_CPU_SIFIVE_U54 RISCV_CPU_TYPE_NAME("sifive-u54") +#define TYPE_RISCV_CPU_MULLVAD_PICORV32 RISCV_CPU_TYPE_NAME("mullvad-picorv32") #if defined(TARGET_RISCV32) # define TYPE_RISCV_CPU_BASE TYPE_RISCV_CPU_BASE32 |