From 3da9c8c0730dc9eb310a635e84e54bf3b24786ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 15 Dec 2020 23:30:19 +0100 Subject: [PATCH] Use a global context for registering "hardwired" devices for consistency. --- .../block/entity/ComputerTileEntity.java | 18 +++--- .../common/vm/ManagedInterruptAllocator.java | 5 +- .../li/cil/oc2/common/vm/VirtualMachine.java | 57 +++++++++++++------ .../vm/VirtualMachineDeviceBusAdapter.java | 21 ++----- .../li/cil/oc2/common/bus/VMDeviceTests.java | 2 +- 5 files changed, 60 insertions(+), 43 deletions(-) diff --git a/src/main/java/li/cil/oc2/common/block/entity/ComputerTileEntity.java b/src/main/java/li/cil/oc2/common/block/entity/ComputerTileEntity.java index e445018e..f244e343 100644 --- a/src/main/java/li/cil/oc2/common/block/entity/ComputerTileEntity.java +++ b/src/main/java/li/cil/oc2/common/block/entity/ComputerTileEntity.java @@ -5,6 +5,7 @@ import li.cil.ceres.api.Serialized; import li.cil.oc2.OpenComputers; import li.cil.oc2.api.bus.DeviceBusElement; import li.cil.oc2.api.bus.device.Device; +import li.cil.oc2.api.bus.device.vm.VMContext; import li.cil.oc2.api.bus.device.vm.VMDeviceLifecycleEventType; import li.cil.oc2.common.block.ComputerBlock; import li.cil.oc2.common.bus.AbstractDeviceBusController; @@ -69,6 +70,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic private static final String ITEMS_NBT_TAG_NAME = "items"; private static final int DEVICE_LOAD_RETRY_INTERVAL = 10 * 20; // In ticks. + private static final int VFS_INTERRUPT = 0x5; /////////////////////////////////////////////////////////////////// @@ -94,7 +96,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic private final VirtIOFileSystemDevice vfs; private ConsoleRunner runner; - private final DeviceItemStackHandler itemHandler = new DeviceItemStackHandler(4); + private final DeviceItemStackHandler itemHandler = new DeviceItemStackHandler(8); /////////////////////////////////////////////////////////////////// @@ -109,9 +111,11 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic terminal = new Terminal(); virtualMachine = new VirtualMachine(busController); - vfs = new VirtIOFileSystemDevice(virtualMachine.board.getMemoryMap(), "scripts", new HostFileSystem()); - vfs.getInterrupt().set(virtualMachine.vmAdapter.claimInterrupt(), virtualMachine.board.getInterruptController()); - virtualMachine.board.addDevice(vfs); + final VMContext context = virtualMachine.vmAdapter.getGlobalContext(); + vfs = new VirtIOFileSystemDevice(context.getMemoryMap(), "scripts", new HostFileSystem()); + context.getInterruptAllocator().claimInterrupt(VFS_INTERRUPT).ifPresent(interrupt -> + vfs.getInterrupt().set(interrupt, context.getInterruptController())); + context.getMemoryRangeAllocator().claimMemoryRange(vfs); setCapabilityIfAbsent(Capabilities.DEVICE_BUS_ELEMENT_CAPABILITY, busElement); setCapabilityIfAbsent(Capabilities.DEVICE_BUS_CONTROLLER_CAPABILITY, busController); @@ -336,9 +340,9 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic } if (compound.contains(ITEMS_NBT_TAG_NAME, NBTTagIds.TAG_COMPOUND)) { - itemHandler.setStackInSlot(0, ItemStack.EMPTY); - itemHandler.setStackInSlot(1, ItemStack.EMPTY); - itemHandler.setStackInSlot(2, ItemStack.EMPTY); + for (int i = 0; i < itemHandler.getSlots(); i++) { + itemHandler.setStackInSlot(i, ItemStack.EMPTY); + } itemHandler.deserializeNBT(compound.getCompound(ITEMS_NBT_TAG_NAME)); } } diff --git a/src/main/java/li/cil/oc2/common/vm/ManagedInterruptAllocator.java b/src/main/java/li/cil/oc2/common/vm/ManagedInterruptAllocator.java index 27292b47..970441f7 100644 --- a/src/main/java/li/cil/oc2/common/vm/ManagedInterruptAllocator.java +++ b/src/main/java/li/cil/oc2/common/vm/ManagedInterruptAllocator.java @@ -24,13 +24,12 @@ public final class ManagedInterruptAllocator implements InterruptAllocator { } public void freeze() { - final long[] words = managedInterrupts.toLongArray(); - managedMask = words.length > 0 ? (int) words[0] : 0; isFrozen = true; } public void invalidate() { claimedInterrupts.andNot(managedInterrupts); + managedInterrupts.clear(); managedMask = 0; } @@ -54,6 +53,7 @@ public final class ManagedInterruptAllocator implements InterruptAllocator { claimedInterrupts.set(interrupt); reservedInterrupts.set(interrupt); managedInterrupts.set(interrupt); + managedMask |= (1 << interrupt); return OptionalInt.of(interrupt); } } @@ -76,6 +76,7 @@ public final class ManagedInterruptAllocator implements InterruptAllocator { claimedInterrupts.set(interrupt); reservedInterrupts.set(interrupt); managedInterrupts.set(interrupt); + managedMask |= (1 << interrupt); return OptionalInt.of(interrupt); } diff --git a/src/main/java/li/cil/oc2/common/vm/VirtualMachine.java b/src/main/java/li/cil/oc2/common/vm/VirtualMachine.java index 07436c08..bac8acd5 100644 --- a/src/main/java/li/cil/oc2/common/vm/VirtualMachine.java +++ b/src/main/java/li/cil/oc2/common/vm/VirtualMachine.java @@ -2,7 +2,11 @@ package li.cil.oc2.common.vm; import li.cil.ceres.api.Serialized; import li.cil.oc2.api.bus.DeviceBusController; +import li.cil.oc2.api.bus.device.vm.InterruptAllocator; +import li.cil.oc2.api.bus.device.vm.MemoryRangeAllocator; +import li.cil.oc2.api.bus.device.vm.VMContext; import li.cil.oc2.common.bus.RPCAdapter; +import li.cil.sedna.api.device.InterruptController; import li.cil.sedna.buildroot.Buildroot; import li.cil.sedna.device.block.ByteBufferBlockDevice; import li.cil.sedna.device.rtc.GoldfishRTC; @@ -25,6 +29,24 @@ public final class VirtualMachine { public static final int REPORTED_CPU_FREQUENCY = 700_000; public static final int ACTUAL_CPU_FREQUENCY = REPORTED_CPU_FREQUENCY * 72; + private static final int UART_INTERRUPT = 0x1; + private static final int HDD_INTERRUPT = 0x2; + private static final int RTC_INTERRUPT = 0x3; + private static final int RPC_INTERRUPT = 0x4; + + private static final ByteBufferBlockDevice ROOT_FS; + + static { + ByteBufferBlockDevice rootfs; + try { + rootfs = ByteBufferBlockDevice.createFromStream(Buildroot.getRootFilesystem(), true); + } catch (final IOException e) { + LOGGER.error(e); + rootfs = ByteBufferBlockDevice.create(0, true); + } + ROOT_FS = rootfs; + } + /////////////////////////////////////////////////////////////////// public final MinecraftRealTimeCounter rtc = new MinecraftRealTimeCounter(); @@ -46,30 +68,31 @@ public final class VirtualMachine { board.getCpu().setFrequency(REPORTED_CPU_FREQUENCY); vmAdapter = new VirtualMachineDeviceBusAdapter(board); + final VMContext context = vmAdapter.getGlobalContext(); + + final MemoryRangeAllocator memoryRangeAllocator = context.getMemoryRangeAllocator(); + final InterruptAllocator interruptAllocator = context.getInterruptAllocator(); + final InterruptController interruptController = context.getInterruptController(); uart = new UART16550A(); - uart.getInterrupt().set(vmAdapter.claimInterrupt(), board.getInterruptController()); - board.addDevice(uart); + interruptAllocator.claimInterrupt(UART_INTERRUPT).ifPresent(interrupt -> + uart.getInterrupt().set(interrupt, interruptController)); + memoryRangeAllocator.claimMemoryRange(uart); - hdd = new VirtIOBlockDevice(board.getMemoryMap()); - hdd.getInterrupt().set(vmAdapter.claimInterrupt(), board.getInterruptController()); - board.addDevice(hdd); - - final ByteBufferBlockDevice blockDevice; - try { - blockDevice = ByteBufferBlockDevice.createFromStream(Buildroot.getRootFilesystem(), true); - hdd.setBlockDevice(blockDevice); - } catch (final IOException e) { - LOGGER.error(e); - } + hdd = new VirtIOBlockDevice(board.getMemoryMap(), ROOT_FS); + interruptAllocator.claimInterrupt(HDD_INTERRUPT).ifPresent(interrupt -> + hdd.getInterrupt().set(interrupt, interruptController)); + memoryRangeAllocator.claimMemoryRange(hdd); final GoldfishRTC rtc = new GoldfishRTC(this.rtc); - rtc.getInterrupt().set(vmAdapter.claimInterrupt(), board.getInterruptController()); - board.addDevice(rtc); + interruptAllocator.claimInterrupt(RTC_INTERRUPT).ifPresent(interrupt -> + rtc.getInterrupt().set(interrupt, interruptController)); + memoryRangeAllocator.claimMemoryRange(rtc); deviceBusSerialDevice = new VirtIOConsoleDevice(board.getMemoryMap()); - deviceBusSerialDevice.getInterrupt().set(vmAdapter.claimInterrupt(), board.getInterruptController()); - board.addDevice(deviceBusSerialDevice); + interruptAllocator.claimInterrupt(RPC_INTERRUPT).ifPresent(interrupt -> + deviceBusSerialDevice.getInterrupt().set(interrupt, interruptController)); + memoryRangeAllocator.claimMemoryRange(deviceBusSerialDevice); rpcAdapter = new RPCAdapter(busController, deviceBusSerialDevice); diff --git a/src/main/java/li/cil/oc2/common/vm/VirtualMachineDeviceBusAdapter.java b/src/main/java/li/cil/oc2/common/vm/VirtualMachineDeviceBusAdapter.java index c91382c9..bf865370 100644 --- a/src/main/java/li/cil/oc2/common/vm/VirtualMachineDeviceBusAdapter.java +++ b/src/main/java/li/cil/oc2/common/vm/VirtualMachineDeviceBusAdapter.java @@ -2,18 +2,15 @@ package li.cil.oc2.common.vm; import li.cil.ceres.api.Serialized; import li.cil.oc2.api.bus.device.Device; -import li.cil.oc2.api.bus.device.vm.VMDevice; -import li.cil.oc2.api.bus.device.vm.VMDeviceLifecycleEventType; -import li.cil.oc2.api.bus.device.vm.VMDeviceLifecycleListener; -import li.cil.oc2.api.bus.device.vm.VMDeviceLoadResult; +import li.cil.oc2.api.bus.device.vm.*; import li.cil.sedna.api.Board; -import li.cil.sedna.riscv.device.R5PlatformLevelInterruptController; import java.util.*; public final class VirtualMachineDeviceBusAdapter { private final Board board; + private final ManagedVMContext globalContext; private final BitSet claimedInterrupts = new BitSet(); private final HashMap deviceContexts = new HashMap<>(); private final ArrayList incompleteLoads = new ArrayList<>(); @@ -32,20 +29,12 @@ public final class VirtualMachineDeviceBusAdapter { public VirtualMachineDeviceBusAdapter(final Board board) { this.board = board; + this.globalContext = new ManagedVMContext(board, claimedInterrupts, reservedInterrupts); this.claimedInterrupts.set(0); } - public int claimInterrupt() { - return claimInterrupt(claimedInterrupts.nextClearBit(0)); - } - - public int claimInterrupt(final int interrupt) { - if (interrupt < 1 || interrupt >= R5PlatformLevelInterruptController.INTERRUPT_COUNT) { - throw new IllegalArgumentException(); - } - - claimedInterrupts.set(interrupt); - return interrupt; + public VMContext getGlobalContext() { + return globalContext; } public boolean load() { diff --git a/src/test/java/li/cil/oc2/common/bus/VMDeviceTests.java b/src/test/java/li/cil/oc2/common/bus/VMDeviceTests.java index cea53f94..512c6261 100644 --- a/src/test/java/li/cil/oc2/common/bus/VMDeviceTests.java +++ b/src/test/java/li/cil/oc2/common/bus/VMDeviceTests.java @@ -138,7 +138,7 @@ public final class VMDeviceTests { return VMDeviceLoadResult.success(); }); - adapter.claimInterrupt(claimedInterrupt); + adapter.getGlobalContext().getInterruptAllocator().claimInterrupt(claimedInterrupt); adapter.addDevices(Collections.singleton(device)); assertTrue(adapter.load());