Skip to content

Commit

Permalink
[dev][virtio-net] sync feature bits with virtio v1.3
Browse files Browse the repository at this point in the history
Add new feature bits for the net device
Since the new feature bits are >= 32, add support for reading higher
than 32bit feature words from the virtio mmio interface.
  • Loading branch information
travisg committed Mar 20, 2024
1 parent c3cf81a commit 3288b15
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 23 deletions.
2 changes: 1 addition & 1 deletion dev/virtio/block/virtio-block.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ status_t virtio_block_init(struct virtio_device *dev, uint32_t host_features) {
VIRTIO_BLK_F_TOPOLOGY |
VIRTIO_BLK_F_DISCARD |
VIRTIO_BLK_F_WRITE_ZEROES);
virtio_set_guest_features(dev, bdev->guest_features);
virtio_set_guest_features(dev, 0, bdev->guest_features);

/* TODO: handle a RO feature */

Expand Down
3 changes: 2 additions & 1 deletion dev/virtio/include/dev/virtio.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ struct virtio_device {

void virtio_reset_device(struct virtio_device *dev);
void virtio_status_acknowledge_driver(struct virtio_device *dev);
void virtio_set_guest_features(struct virtio_device *dev, uint32_t features);
uint32_t virtio_read_host_feature_word(struct virtio_device *dev, uint32_t word);
void virtio_set_guest_features(struct virtio_device *dev, uint32_t word, uint32_t features);
void virtio_status_driver_ok(struct virtio_device *dev);

/* api used by devices to interact with the virtio bus */
Expand Down
2 changes: 1 addition & 1 deletion dev/virtio/net/include/dev/virtio/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include <sys/types.h>
#include <dev/virtio.h>

status_t virtio_net_init(struct virtio_device *dev, uint32_t host_features) __NONNULL();
status_t virtio_net_init(struct virtio_device *dev) __NONNULL();
status_t virtio_net_start(void);

/* return the count of virtio interfaces found */
Expand Down
61 changes: 55 additions & 6 deletions dev/virtio/net/virtio-net.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <dev/virtio/net.h>

#include <stdlib.h>
#include <inttypes.h>
#include <lk/debug.h>
#include <assert.h>
#include <lk/trace.h>
Expand All @@ -27,25 +28,47 @@ struct virtio_net_config {
uint8_t mac[6];
uint16_t status;
uint16_t max_virtqueue_pairs;
uint16_t mtu;
uint32_t speed;
uint8_t duplex;
uint8_t rss_max_key_size;
uint16_t rss_max_indirection_table_length;
uint32_t supported_hash_types;
uint32_t supported_tunnel_types;
};
STATIC_ASSERT(sizeof(struct virtio_net_config) == 10);
STATIC_ASSERT(sizeof(struct virtio_net_config) == 28);

struct virtio_net_hdr {
#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1
#define VIRTIO_NET_HDR_F_DATA_VALID 2
#define VIRTIO_NET_HDR_F_RSC_INFO 4
uint8_t flags;
#define VIRTIO_NET_HDR_GSO_NONE 0
#define VIRTIO_NET_HDR_GSO_TCPV4 1
#define VIRTIO_NET_HDR_GSO_UDP 3
#define VIRTIO_NET_HDR_GSO_TCPV6 4
#define VIRTIO_NET_HDR_GSO_UDP_L4 5
#define VIRTIO_NET_HDR_GSO_ECN 0x80
uint8_t gso_type;
uint16_t hdr_len;
uint16_t gso_size;
uint16_t csum_start;
uint16_t csum_offset;
uint16_t num_buffers; // unused in tx

// Only if VIRTIO_NET_HASH_REPORT negotiated
//uint32_t hash_value;
//uint16_t hash_report;
//uint16_t padding_reserved;
};
STATIC_ASSERT(sizeof(struct virtio_net_hdr) == 12);

#define VIRTIO_NET_F_CSUM (1<<0)
#define VIRTIO_NET_F_GUEST_CSUM (1<<1)
#define VIRTIO_NET_F_CTRL_GUEST_OFFLOADS (1<<2)
#define VIRTIO_NET_F_MTU (1<<3)
#define VIRTIO_NET_F_MAC (1<<5)
#define VIRTIO_NET_F_GSO (1<<6)
#define VIRTIO_NET_F_GSO (1<<6) // removed in v1.3
#define VIRTIO_NET_F_GUEST_TSO4 (1<<7)
#define VIRTIO_NET_F_GUEST_TSO6 (1<<8)
#define VIRTIO_NET_F_GUEST_ECN (1<<9)
Expand All @@ -62,6 +85,18 @@ STATIC_ASSERT(sizeof(struct virtio_net_hdr) == 12);
#define VIRTIO_NET_F_GUEST_ANNOUNCE (1<<21)
#define VIRTIO_NET_F_MQ (1<<22)
#define VIRTIO_NET_F_CTRL_MAC_ADDR (1<<23)
#define VIRTIO_NET_F_HASH_TUNNEL (1ULL<<51)
#define VIRTIO_NET_F_VQ_NOTF_COAL (1ULL<<52)
#define VIRTIO_NET_F_NOTF_COAL (1ULL<<53)
#define VIRTIO_NET_F_GUEST_USO4 (1ULL<<54)
#define VIRTIO_NET_F_GUEST_USO6 (1ULL<<55)
#define VIRTIO_NET_F_HOST_USO (1ULL<<56)
#define VIRTIO_NET_F_HASH_REPORT (1ULL<<57)
#define VIRTIO_NET_F_GUEST_HDRLEN (1ULL<<59)
#define VIRTIO_NET_F_RSS (1ULL<<60)
#define VIRTIO_NET_F_RSC_EXT (1ULL<<61)
#define VIRTIO_NET_F_STANDBY (1ULL<<62)
#define VIRTIO_NET_F_SPEED_DUPLEX (1ULL<<63)

#define VIRTIO_NET_S_LINK_UP (1<<0)
#define VIRTIO_NET_S_ANNOUNCE (1<<1)
Expand Down Expand Up @@ -98,11 +133,12 @@ static status_t virtio_net_queue_rx(struct virtio_net_dev *ndev, pktbuf_t *p);
// XXX remove need for this
static struct virtio_net_dev *the_ndev;

static void dump_feature_bits(uint32_t feature) {
printf("virtio-net host features (0x%x):", feature);
static void dump_feature_bits(uint64_t feature) {
printf("virtio-net host features (%#" PRIx64 "):", feature);
if (feature & VIRTIO_NET_F_CSUM) printf(" CSUM");
if (feature & VIRTIO_NET_F_GUEST_CSUM) printf(" GUEST_CSUM");
if (feature & VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) printf(" CTRL_GUEST_OFFLOADS");
if (feature & VIRTIO_NET_F_MTU) printf(" MTU");
if (feature & VIRTIO_NET_F_MAC) printf(" MAC");
if (feature & VIRTIO_NET_F_GSO) printf(" GSO");
if (feature & VIRTIO_NET_F_GUEST_TSO4) printf(" GUEST_TSO4");
Expand All @@ -121,11 +157,23 @@ static void dump_feature_bits(uint32_t feature) {
if (feature & VIRTIO_NET_F_GUEST_ANNOUNCE) printf(" GUEST_ANNOUNCE");
if (feature & VIRTIO_NET_F_MQ) printf(" MQ");
if (feature & VIRTIO_NET_F_CTRL_MAC_ADDR) printf(" CTRL_MAC_ADDR");
if (feature & VIRTIO_NET_F_HASH_TUNNEL) printf(" HASH_TUNNEL");
if (feature & VIRTIO_NET_F_VQ_NOTF_COAL) printf(" VQ_NOTF_COAL");
if (feature & VIRTIO_NET_F_NOTF_COAL) printf(" NOTF_COAL");
if (feature & VIRTIO_NET_F_GUEST_USO4) printf(" GUEST_USO4");
if (feature & VIRTIO_NET_F_GUEST_USO6) printf(" GUEST_USO6");
if (feature & VIRTIO_NET_F_HOST_USO) printf(" HOST_USO");
if (feature & VIRTIO_NET_F_HASH_REPORT) printf(" HASH_REPORT");
if (feature & VIRTIO_NET_F_GUEST_HDRLEN) printf(" GUEST_HDRLEN");
if (feature & VIRTIO_NET_F_RSS) printf(" RSS");
if (feature & VIRTIO_NET_F_RSC_EXT) printf(" RSC_EXT");
if (feature & VIRTIO_NET_F_STANDBY) printf(" STANDBY");
if (feature & VIRTIO_NET_F_SPEED_DUPLEX) printf(" SPEED_DUPLEX");
printf("\n");
}

status_t virtio_net_init(struct virtio_device *dev, uint32_t host_features) {
LTRACEF("dev %p, host_features 0x%x\n", dev, host_features);
status_t virtio_net_init(struct virtio_device *dev) {
LTRACEF("dev %p\n", dev);

/* allocate a new net device */
struct virtio_net_dev *ndev = calloc(1, sizeof(struct virtio_net_dev));
Expand All @@ -146,6 +194,7 @@ status_t virtio_net_init(struct virtio_device *dev, uint32_t host_features) {
virtio_status_acknowledge_driver(dev);

// XXX check features bits and ack/nak them
uint64_t host_features = virtio_read_host_feature_word(dev, 0) | (uint64_t)virtio_read_host_feature_word(dev, 1) << 32;
dump_feature_bits(host_features);

/* set our irq handler */
Expand Down
17 changes: 12 additions & 5 deletions dev/virtio/virtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ int virtio_mmio_detect(void *ptr, uint count, const uint irqs[], size_t stride)
continue;
}

// TODO: handle version 2

#if LOCAL_TRACE
if (mmio->device_id != 0) {
dump_mmio_config(mmio);
Expand All @@ -156,7 +158,7 @@ int virtio_mmio_detect(void *ptr, uint count, const uint irqs[], size_t stride)
dev->mmio_config = mmio;
dev->config_ptr = (void *)mmio->config;

status_t err = virtio_block_init(dev, mmio->host_features);
status_t err = virtio_block_init(dev, virtio_read_host_feature_word(dev, 0));
if (err >= 0) {
// good device
dev->valid = true;
Expand All @@ -173,7 +175,7 @@ int virtio_mmio_detect(void *ptr, uint count, const uint irqs[], size_t stride)
dev->mmio_config = mmio;
dev->config_ptr = (void *)mmio->config;

status_t err = virtio_net_init(dev, mmio->host_features);
status_t err = virtio_net_init(dev);
if (err >= 0) {
// good device
dev->valid = true;
Expand All @@ -190,7 +192,7 @@ int virtio_mmio_detect(void *ptr, uint count, const uint irqs[], size_t stride)
dev->mmio_config = mmio;
dev->config_ptr = (void *)mmio->config;

status_t err = virtio_gpu_init(dev, mmio->host_features);
status_t err = virtio_gpu_init(dev, virtio_read_host_feature_word(dev, 0));
if (err >= 0) {
// good device
dev->valid = true;
Expand Down Expand Up @@ -367,11 +369,16 @@ void virtio_status_driver_ok(struct virtio_device *dev) {
dev->mmio_config->status |= VIRTIO_STATUS_DRIVER_OK;
}

void virtio_set_guest_features(struct virtio_device *dev, uint32_t features) {
dev->mmio_config->guest_features_sel = 0;
void virtio_set_guest_features(struct virtio_device *dev, uint32_t word, uint32_t features) {
dev->mmio_config->guest_features_sel = word;
dev->mmio_config->guest_features = features;
}

uint32_t virtio_read_host_feature_word(struct virtio_device *dev, uint32_t word) {
dev->mmio_config->host_features_sel = word;
return dev->mmio_config->host_features;
}

static void virtio_init(uint level) {
}

Expand Down
28 changes: 19 additions & 9 deletions dev/virtio/virtio_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,42 @@
#include <lk/compiler.h>
#include <stdint.h>

// V1 config
struct virtio_mmio_config {
/* 0x00 */ uint32_t magic;
/* 0x00 */
uint32_t magic;
uint32_t version;
uint32_t device_id;
uint32_t vendor_id;
/* 0x10 */ uint32_t host_features;
/* 0x10 */
uint32_t host_features;
uint32_t host_features_sel;
uint32_t __reserved0[2];
/* 0x20 */ uint32_t guest_features;
/* 0x20 */
uint32_t guest_features;
uint32_t guest_features_sel;
uint32_t guest_page_size;
uint32_t __reserved1[1];
/* 0x30 */ uint32_t queue_sel;
/* 0x30 */
uint32_t queue_sel;
uint32_t queue_num_max;
uint32_t queue_num;
uint32_t queue_align;
/* 0x40 */ uint32_t queue_pfn;
/* 0x40 */
uint32_t queue_pfn;
uint32_t __reserved2[3];
/* 0x50 */ uint32_t queue_notify;
/* 0x50 */
uint32_t queue_notify;
uint32_t __reserved3[3];
/* 0x60 */ uint32_t interrupt_status;
/* 0x60 */
uint32_t interrupt_status;
uint32_t interrupt_ack;
uint32_t __reserved4[2];
/* 0x70 */ uint32_t status;
/* 0x70 */
uint32_t status;
uint8_t __reserved5[0x8c];
/* 0x100 */ uint32_t config[0];
/* 0x100 */
uint32_t config[0];
};

STATIC_ASSERT(sizeof(struct virtio_mmio_config) == 0x100);
Expand Down

0 comments on commit 3288b15

Please sign in to comment.