Skip to content

Commit

Permalink
[Workaround] Implement virtio-rng device
Browse files Browse the repository at this point in the history
  • Loading branch information
shengwen-tw committed Jan 29, 2025
1 parent a1d688e commit 261dcdc
Show file tree
Hide file tree
Showing 5 changed files with 360 additions and 0 deletions.
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ ifeq ($(call has, VIRTIOBLK), 1)
endif
endif

# virtio-rng
ENABLE_VIRTIORNG ?= 1
$(call set-feature, VIRTIORNG)
ifeq ($(call has, VIRTIORNG), 1)
OBJS_EXTRA += virtio-rng.o
endif

NETDEV ?= tap
# virtio-net
ENABLE_VIRTIONET ?= 1
Expand Down
49 changes: 49 additions & 0 deletions device.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,52 @@ void virtio_input_update_mouse_button_state(uint32_t button, bool pressed);
void virtio_input_update_cursor(uint32_t x, uint32_t y);
#endif /* SEMU_HAS(VIRTIOINPUT) */

/* VirtIO-RNG */

#if SEMU_HAS(VIRTIORNG)

#define IRQ_VRNG 7
#define IRQ_VRNG_BIT (1 << IRQ_VRNG)

typedef struct {
uint32_t QueueNum;
uint32_t QueueDesc;
uint32_t QueueAvail;
uint32_t QueueUsed;
uint16_t last_avail;
bool ready;
} virtio_rng_queue_t;

typedef struct {
/* feature negotiation */
uint32_t DeviceFeaturesSel;
uint32_t DriverFeatures;
uint32_t DriverFeaturesSel;
/* queue config */
uint32_t QueueSel;
virtio_rng_queue_t queues[1];
/* status */
uint32_t Status;
uint32_t InterruptStatus;
/* supplied by environment */
uint32_t *ram;
} virtio_rng_state_t;

void virtio_rng_read(hart_t *vm,
virtio_rng_state_t *rng,
uint32_t addr,
uint8_t width,
uint32_t *value);

void virtio_rng_write(hart_t *vm,
virtio_rng_state_t *vrng,
uint32_t addr,
uint8_t width,
uint32_t value);

void virtio_rng_init(virtio_rng_state_t *vrng);
#endif /* SEMU_HAS(VIRTIORNG) */

/* ACLINT MTIMER */
typedef struct {
/* A MTIMER device has two separate base addresses: one for the MTIME
Expand Down Expand Up @@ -393,6 +439,9 @@ typedef struct {
#if SEMU_HAS(VIRTIOINPUT)
virtio_input_state_t vkeyboard;
virtio_input_state_t vmouse;
#endif
#if SEMU_HAS(VIRTIORNG)
virtio_rng_state_t vrng;
#endif
/* ACLINT */
mtimer_state_t mtimer;
Expand Down
28 changes: 28 additions & 0 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,18 @@ static void emu_update_vinput_mouse_interrupts(vm_t *vm)
}
#endif

#if SEMU_HAS(VIRTIORNG)
static void emu_update_vrng_interrupts(vm_t *vm)
{
emu_state_t *data = PRIV(vm->hart[0]);
if (data->vrng.InterruptStatus)
data->plic.active |= IRQ_VRNG_BIT;
else
data->plic.active &= ~IRQ_VRNG_BIT;
plic_update_interrupts(vm, &data->plic);
}
#endif

static void emu_update_timer_interrupt(hart_t *hart)
{
emu_state_t *data = PRIV(hart);
Expand Down Expand Up @@ -189,6 +201,12 @@ static void mem_load(hart_t *hart,
value);
emu_update_vinput_mouse_interrupts(hart->vm);
return;
#endif
#if SEMU_HAS(VIRTIORNG)
case 0x49: /* virtio-rng */
virtio_rng_read(hart, &data->vrng, addr & 0xFFFFF, width, value);
emu_update_vrng_interrupts(hart->vm);
return;
#endif
}
}
Expand Down Expand Up @@ -261,6 +279,12 @@ static void mem_store(hart_t *hart,
value);
emu_update_vinput_mouse_interrupts(hart->vm);
return;
#endif
#if SEMU_HAS(VIRTIORNG)
case 0x49: /* virtio-rng */
virtio_rng_write(hart, &data->vrng, addr & 0xFFFFF, width, value);
emu_update_vrng_interrupts(hart->vm);
return;
#endif
}
}
Expand Down Expand Up @@ -709,6 +733,10 @@ static int semu_start(int argc, char **argv)
emu.vmouse.ram = emu.ram;
virtio_input_init(&(emu.vmouse));
#endif
#if SEMU_HAS(VIRTIORNG)
emu.vrng.ram = emu.ram;
virtio_rng_init(&(emu.vrng));
#endif

/* Emulate */
uint32_t peripheral_update_ctr = 0;
Expand Down
8 changes: 8 additions & 0 deletions minimal.dts
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,13 @@
interrupts = <6>;
};
#endif

#if SEMU_FEATURE_VIRTIORNG
rng0: virtio@4900000 {
compatible = "virtio,mmio";
reg = <0x4900000 0x200>;
interrupts = <7>;
};
#endif
};
};
Loading

0 comments on commit 261dcdc

Please sign in to comment.