Gave up and accepted we need bootargs (for now), so those can be set on board now.

This commit is contained in:
Florian Nücke
2020-09-25 15:46:03 +02:00
parent b4c8bfcdf9
commit c7990ea8bc
3 changed files with 140 additions and 91 deletions

View File

@@ -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);

View File

@@ -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());
}
}
}
}

View File

@@ -48,6 +48,8 @@ public final class R5Board implements Steppable, Resettable {
private final List<MemoryMappedDevice> devices = new ArrayList<>();
private final List<Steppable> 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;
}