Use a global context for registering "hardwired" devices for consistency.

This commit is contained in:
Florian Nücke
2020-12-15 23:30:19 +01:00
parent ec3cacd57e
commit 3da9c8c073
5 changed files with 60 additions and 43 deletions

View File

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

View File

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

View File

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

View File

@@ -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<VMDevice, ManagedVMContext> deviceContexts = new HashMap<>();
private final ArrayList<VMDevice> 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() {

View File

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