Skip to content

Commit

Permalink
Merge pull request #70 from shengwen-tw/virtio-rng
Browse files Browse the repository at this point in the history
Implement VirtIO RNG device
  • Loading branch information
jserv authored Feb 1, 2025
2 parents d42a013 + 9b3b4aa commit 50fbf07
Show file tree
Hide file tree
Showing 6 changed files with 362 additions and 1 deletion.
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,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
3 changes: 2 additions & 1 deletion configs/linux.config
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_TTY_PRINTK is not set
# CONFIG_VIRTIO_CONSOLE is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_VIRTIO=y
CONFIG_DEVMEM=y
# CONFIG_TCG_TPM is not set
# CONFIG_XILLYBUS is not set
Expand Down
49 changes: 49 additions & 0 deletions device.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,52 @@ void virtio_blk_write(hart_t *vm,
uint32_t *virtio_blk_init(virtio_blk_state_t *vblk, char *disk_file);
#endif /* SEMU_HAS(VIRTIOBLK) */

/* VirtIO-RNG */

#if SEMU_HAS(VIRTIORNG)

#define IRQ_VRNG 4
#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(void);
#endif /* SEMU_HAS(VIRTIORNG) */

/* ACLINT MTIMER */
typedef struct {
/* A MTIMER device has two separate base addresses: one for the MTIME
Expand Down Expand Up @@ -272,6 +318,9 @@ typedef struct {
#endif
#if SEMU_HAS(VIRTIOBLK)
virtio_blk_state_t vblk;
#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 @@ -72,6 +72,18 @@ static void emu_update_vblk_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 @@ -137,6 +149,12 @@ static void mem_load(hart_t *hart,
aclint_sswi_read(hart, &data->sswi, addr & 0xFFFFF, width, value);
aclint_sswi_update_interrupts(hart, &data->sswi);
return;
#if SEMU_HAS(VIRTIORNG)
case 0x46: /* virtio-rng */
virtio_rng_read(hart, &data->vrng, addr & 0xFFFFF, width, value);
emu_update_vrng_interrupts(hart->vm);
return;
#endif
}
}
vm_set_exception(hart, RV_EXC_LOAD_FAULT, hart->exc_val);
Expand Down Expand Up @@ -191,6 +209,12 @@ static void mem_store(hart_t *hart,
aclint_sswi_write(hart, &data->sswi, addr & 0xFFFFF, width, value);
aclint_sswi_update_interrupts(hart, &data->sswi);
return;
#if SEMU_HAS(VIRTIORNG)
case 0x46: /* virtio-rng */
virtio_rng_write(hart, &data->vrng, addr & 0xFFFFF, width, value);
emu_update_vrng_interrupts(hart->vm);
return;
#endif
}
}
vm_set_exception(hart, RV_EXC_STORE_FAULT, hart->exc_val);
Expand Down Expand Up @@ -617,6 +641,10 @@ static int semu_start(int argc, char **argv)
#if SEMU_HAS(VIRTIOBLK)
emu.vblk.ram = emu.ram;
emu.disk = virtio_blk_init(&(emu.vblk), disk_file);
#endif
#if SEMU_HAS(VIRTIORNG)
emu.vrng.ram = emu.ram;
virtio_rng_init();
#endif
/* Set up ACLINT */
semu_timer_init(&emu.mtimer.mtime, CLOCK_FREQ);
Expand Down
8 changes: 8 additions & 0 deletions minimal.dts
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,13 @@
interrupts = <3>;
};
#endif

#if SEMU_FEATURE_VIRTIORNG
rng0: virtio@4600000 {
compatible = "virtio,mmio";
reg = <0x4600000 0x200>;
interrupts = <4>;
};
#endif
};
};
Loading

0 comments on commit 50fbf07

Please sign in to comment.