From c7990ea8bcd67a8f73d4806178f64fe1b62693d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Fri, 25 Sep 2020 15:46:03 +0200 Subject: [PATCH] Gave up and accepted we need bootargs (for now), so those can be set on board now. --- src/main/java/li/cil/circuity/Main.java | 26 +-- .../circuity/client/gui/RISCVTestScreen.java | 187 +++++++++++------- .../li/cil/circuity/vm/riscv/R5Board.java | 18 +- 3 files changed, 140 insertions(+), 91 deletions(-) diff --git a/src/main/java/li/cil/circuity/Main.java b/src/main/java/li/cil/circuity/Main.java index a30defb9..bce60515 100644 --- a/src/main/java/li/cil/circuity/Main.java +++ b/src/main/java/li/cil/circuity/Main.java @@ -12,10 +12,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.InputStreamReader; +import java.io.*; import java.util.ArrayList; public final class Main { @@ -35,25 +32,28 @@ public final class Main { } private static void runEmulator() throws Exception { + final String firmware = "buildroot/output/images/fw_jump.bin"; + final String kernel = "buildroot/output/images/Image"; + final File rootfsFile = new File("buildroot/output/images/rootfs.ext2"); + final R5Board board = new R5Board(); final PhysicalMemory rom = Memory.create(128 * 1024); final PhysicalMemory memory = Memory.create(32 * 1014 * 1024); final UART16550A uart = new UART16550A(); - final VirtIOBlockDevice hdd = new VirtIOBlockDevice(board.getMemoryMap(), ByteBufferBlockDevice.create(32 * 1024 * 1024, false)); + final VirtIOBlockDevice hdd = new VirtIOBlockDevice(board.getMemoryMap(), ByteBufferBlockDevice.createFromFile(rootfsFile, true)); + + uart.getInterrupt().set(0xA, board.getInterruptController()); + hdd.getInterrupt().set(0x1, board.getInterruptController()); board.addDevice(0x80000000, rom); board.addDevice(0x80000000 + 0x400000, memory); board.addDevice(uart); board.addDevice(hdd); - uart.getInterrupt().set(0xA, board.getInterruptController()); - hdd.getInterrupt().set(0x1, board.getInterruptController()); + board.setBootargs("console=ttyS0 root=/dev/vda ro"); board.reset(); - final String firmware = "buildroot/fw_jump.bin"; - final String kernel = "buildroot/Image"; - loadProgramFile(memory, 0, kernel); loadProgramFile(rom, 0, firmware); @@ -105,8 +105,10 @@ public final class Main { board.addDevice(0x80000000, rom); board.addDevice(0x80000000 + 0x400000, memory); - final String firmware = "buildroot/fw_jump.bin"; - final String kernel = "buildroot/Image"; + board.setBootargs("console=ttyS0"); + + final String firmware = "buildroot/output/images/fw_jump.bin"; + final String kernel = "buildroot/output/images/Image_Benchmark"; LOGGER.info("Waiting for profiler..."); Thread.sleep(5 * 1000); diff --git a/src/main/java/li/cil/circuity/client/gui/RISCVTestScreen.java b/src/main/java/li/cil/circuity/client/gui/RISCVTestScreen.java index 2c65322e..7ac6f7ba 100644 --- a/src/main/java/li/cil/circuity/client/gui/RISCVTestScreen.java +++ b/src/main/java/li/cil/circuity/client/gui/RISCVTestScreen.java @@ -7,8 +7,10 @@ import li.cil.circuity.api.vm.device.memory.Sizes; import li.cil.circuity.client.gui.terminal.Terminal; import li.cil.circuity.client.gui.terminal.TerminalInput; import li.cil.circuity.common.vm.VirtualMachineRunner; +import li.cil.circuity.vm.device.ByteBufferBlockDevice; import li.cil.circuity.vm.device.UART16550A; import li.cil.circuity.vm.device.memory.Memory; +import li.cil.circuity.vm.device.virtio.VirtIOBlockDevice; import li.cil.circuity.vm.device.virtio.VirtIOConsoleDevice; import li.cil.circuity.vm.device.virtio.VirtIOKeyboardDevice; import li.cil.circuity.vm.riscv.R5Board; @@ -19,6 +21,7 @@ import org.apache.logging.log4j.Logger; import org.lwjgl.glfw.GLFW; import java.io.BufferedInputStream; +import java.io.File; import java.io.FileInputStream; import java.util.Objects; @@ -47,80 +50,16 @@ public final class RISCVTestScreen extends Screen { protected void init() { super.init(); - final R5Board board = new R5Board(); - final PhysicalMemory rom = Memory.create(128 * 1024); - final PhysicalMemory memory = Memory.create(128 * 1014 * 1024); - - if (USE_VIRT_IO) { - uart = new UART16550A(); - uart.getInterrupt().set(0xA, board.getInterruptController()); - - board.addDevice(uart); - } else { - console = new VirtIOConsoleDevice(board.getMemoryMap()); - console.getInterrupt().set(0x1, board.getInterruptController()); - - keyboard = new VirtIOKeyboardDevice(board.getMemoryMap()); - keyboard.getInterrupt().set(0x2, board.getInterruptController()); - - board.addDevice(console); - board.addDevice(keyboard); + try { + createVirtualMachine(); + } catch (final Throwable e) { + LOGGER.error(e); + if (minecraft != null && minecraft.player != null) { + minecraft.player.sendChatMessage("Failed creating VM: " + e.toString()); + minecraft.displayGuiScreen(null); + } } - board.addDevice(0x80000000, rom); - board.addDevice(0x80000000 + 0x400000, memory); - board.reset(); - - final String firmware = "../buildroot/fw_jump.bin"; - final String kernel = "../buildroot/Image"; - - loadProgramFile(memory, kernel); - loadProgramFile(rom, firmware); - - runner = new VirtualMachineRunner(board) { - // Thread-local buffers for lock-free read/writes in inner loop. - private final ByteArrayFIFOQueue outputBuffer = new ByteArrayFIFOQueue(1024); - private final ByteArrayFIFOQueue inputBuffer = new ByteArrayFIFOQueue(32); - - @Override - protected void handleBeforeRun() { - int value; - while ((value = terminal.readInput()) != -1) { - inputBuffer.enqueue((byte) value); - } - } - - @Override - protected void step() { - if (USE_VIRT_IO) { - boolean wrote = false; - while (!inputBuffer.isEmpty() && console.canPutByte()) { - wrote = true; - console.putByte(inputBuffer.dequeueByte()); - } - if (wrote) { - console.flush(); - } - } else { - while (!inputBuffer.isEmpty() && uart.canPutByte()) { - uart.putByte(inputBuffer.dequeueByte()); - } - } - - int value; - while ((value = uart.read()) != -1) { - outputBuffer.enqueue((byte) value); - } - } - - @Override - protected void handleAfterRun() { - while (!outputBuffer.isEmpty()) { - terminal.putOutput(outputBuffer.dequeueByte()); - } - } - }; - if (minecraft != null) { minecraft.keyboardListener.enableRepeatEvents(true); } @@ -139,8 +78,10 @@ public final class RISCVTestScreen extends Screen { public void tick() { super.tick(); - // Allow VM to run for the next second. - runner.tick(); + if (runner != null) { + // Allow VM to run for the next second. + runner.tick(); + } } @Override @@ -207,6 +148,56 @@ public final class RISCVTestScreen extends Screen { return super.keyReleased(keyCode, scanCode, modifiers); } + private void createVirtualMachine() throws Throwable { + final String firmware = "../buildroot/output/images/fw_jump.bin"; + final String kernel = "../buildroot/output/images/Image"; + final File rootfsFile = new File("../buildroot/output/images/rootfs.ext2"); + + final R5Board board = new R5Board(); + final PhysicalMemory rom = Memory.create(128 * 1024); + final PhysicalMemory memory = Memory.create(32 * 1014 * 1024); + final VirtIOBlockDevice hdd = new VirtIOBlockDevice(board.getMemoryMap(), ByteBufferBlockDevice.createFromFile(rootfsFile, true)); + + final StringBuilder bootargs = new StringBuilder(); + bootargs.append("root=/dev/vda ro"); + + if (USE_VIRT_IO) { + console = new VirtIOConsoleDevice(board.getMemoryMap()); + keyboard = new VirtIOKeyboardDevice(board.getMemoryMap()); + + console.getInterrupt().set(0x1, board.getInterruptController()); + keyboard.getInterrupt().set(0x2, board.getInterruptController()); + + board.addDevice(console); + board.addDevice(keyboard); + + bootargs.append(" console=hvc0"); + } else { + uart = new UART16550A(); + + uart.getInterrupt().set(0xA, board.getInterruptController()); + + board.addDevice(uart); + + bootargs.append(" console=ttyS0"); + } + + hdd.getInterrupt().set(0x3, board.getInterruptController()); + + board.addDevice(hdd); + board.addDevice(0x80000000, rom); + board.addDevice(0x80000000 + 0x400000, memory); + + board.setBootargs(bootargs.toString()); + + board.reset(); + + loadProgramFile(memory, kernel); + loadProgramFile(rom, firmware); + + runner = new ConsoleRunner(board); + } + private static void loadProgramFile(final PhysicalMemory memory, final String path) { try { try (final FileInputStream is = new FileInputStream(path)) { @@ -219,4 +210,52 @@ public final class RISCVTestScreen extends Screen { LOGGER.error(e); } } + + private final class ConsoleRunner extends VirtualMachineRunner { + // Thread-local buffers for lock-free read/writes in inner loop. + private final ByteArrayFIFOQueue outputBuffer = new ByteArrayFIFOQueue(1024); + private final ByteArrayFIFOQueue inputBuffer = new ByteArrayFIFOQueue(32); + + public ConsoleRunner(final R5Board board) { + super(board); + } + + @Override + protected void handleBeforeRun() { + int value; + while ((value = terminal.readInput()) != -1) { + inputBuffer.enqueue((byte) value); + } + } + + @Override + protected void step() { + if (USE_VIRT_IO) { + boolean wrote = false; + while (!inputBuffer.isEmpty() && console.canPutByte()) { + wrote = true; + console.putByte(inputBuffer.dequeueByte()); + } + if (wrote) { + console.flush(); + } + } else { + while (!inputBuffer.isEmpty() && uart.canPutByte()) { + uart.putByte(inputBuffer.dequeueByte()); + } + } + + int value; + while ((value = uart.read()) != -1) { + outputBuffer.enqueue((byte) value); + } + } + + @Override + protected void handleAfterRun() { + while (!outputBuffer.isEmpty()) { + terminal.putOutput(outputBuffer.dequeueByte()); + } + } + } } diff --git a/src/main/java/li/cil/circuity/vm/riscv/R5Board.java b/src/main/java/li/cil/circuity/vm/riscv/R5Board.java index 536f841d..797f3d51 100644 --- a/src/main/java/li/cil/circuity/vm/riscv/R5Board.java +++ b/src/main/java/li/cil/circuity/vm/riscv/R5Board.java @@ -48,6 +48,8 @@ public final class R5Board implements Steppable, Resettable { private final List devices = new ArrayList<>(); private final List steppableDevices = new ArrayList<>(); + private String bootargs; + public R5Board() { memoryMap = new SimpleMemoryMap(); rtc = cpu = new R5CPU(memoryMap); @@ -80,6 +82,13 @@ public final class R5Board implements Steppable, Resettable { return plic; } + public void setBootargs(final String value) { + if (value != null && value.length() > 64) { + throw new IllegalArgumentException(); + } + this.bootargs = value; + } + public boolean addDevice(final int address, final MemoryMappedDevice device) { if (device.getLength() == 0) { return false; @@ -221,11 +230,10 @@ public final class R5Board implements Steppable, Resettable { DeviceTreeRegistry.visit(root, memoryMap, device); } - root.putChild("chosen", chosen -> chosen - .addProp("bootargs", "console=ttyS0")); - -// root.putChild("chosen", chosen -> chosen -// .addProp("bootargs", "console=hvc0")); + if (bootargs != null) { + root.putChild("chosen", chosen -> chosen + .addProp("bootargs", bootargs)); + } return root; }