Skip to content

Commit 502aae1

Browse files
use buddy allocator for tx queue
1 parent fb20a66 commit 502aae1

File tree

3 files changed

+64
-24
lines changed

3 files changed

+64
-24
lines changed

include/buddy_allocator.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ void buddy_init(buddy_allocator_t* alloc, int min_order, int max_order, int grow
103103
* @param size Requested size in bytes.
104104
* @return Pointer to allocated memory, or NULL if out of memory.
105105
*
106+
* @note Alignment of the returned pointer is at least the largest power-of-two
107+
* that divides sizeof(buddy_header_t); effectively 8 bytes with the current
108+
* header layout. The underlying block base is aligned to its block size.
109+
*
106110
* If the active region cannot satisfy the request, a new region is
107111
* automatically allocated of size (1 << grow_order). Returned blocks
108112
* are aligned to their block size (power of two).
@@ -138,6 +142,10 @@ void buddy_destroy(buddy_allocator_t *alloc);
138142
* @param s NUL-terminated string to duplicate.
139143
* @return Newly allocated string copy, or NULL on OOM.
140144
*
145+
* @note Alignment of the returned pointer is at least the largest power-of-two
146+
* that divides sizeof(buddy_header_t); effectively 8 bytes with the current
147+
* header layout. The underlying block base is aligned to its block size.
148+
*
141149
* The returned string is allocated from the buddy allocator's
142150
* private heap and must be freed with @ref buddy_free.
143151
*/
@@ -149,11 +157,39 @@ char* buddy_strdup(buddy_allocator_t* alloc, const char *s);
149157
* Works like krealloc(): if ptr is NULL, behaves like buddy_malloc().
150158
* If size == 0, frees the block and returns NULL.
151159
*
160+
* @note Alignment of the returned pointer is at least the largest power-of-two
161+
* that divides sizeof(buddy_header_t); effectively 8 bytes with the current
162+
* header layout. The underlying block base is aligned to its block size.
163+
*
152164
* @param alloc Buddy allocator to allocate from.
153165
* @param ptr Pointer previously returned by buddy_malloc().
154166
* @param size New desired size in bytes.
155167
* @return Pointer to resized block, or NULL on OOM.
156168
*/
157169
void* buddy_realloc(buddy_allocator_t* alloc, void *ptr, size_t size);
158170

171+
/**
172+
* @brief Allocate zero-initialised memory from the buddy allocator.
173+
*
174+
* Behaves like standard calloc(): allocates space for @p num elements of
175+
* @p size bytes each, rounds up to the allocator’s block size, and fills
176+
* the returned block with zeroes.
177+
*
178+
* @param alloc Buddy allocator to allocate from.
179+
* @param num Number of elements to allocate.
180+
* @param size Size of each element in bytes.
181+
* @return Pointer to zero-initialised memory, or NULL on OOM.
182+
*
183+
* @note Alignment of the returned pointer is at least the largest power-of-two
184+
* that divides sizeof(buddy_header_t); effectively 8 bytes with the current
185+
* header layout. The underlying block base is aligned to its block size.
186+
*
187+
* @see buddy_malloc(), buddy_free(), buddy_realloc(), buddy_destroy()
188+
*/
159189
void* buddy_calloc(buddy_allocator_t* alloc, size_t num, size_t size);
190+
191+
/**
192+
* Ensure that if we make changes here, pointers returned by the buddy allocator
193+
* are still aligned to at least 8 bytes, as some systems assume this.
194+
*/
195+
_Static_assert((sizeof(buddy_header_t) % 8) == 0, "Alignment too small");

modules/virtio_net/virtio_net.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include <kernel.h>
22
#include "virtio_net.h"
33

4+
buddy_allocator_t tx_buffer_allocator;
5+
46
static bool virtio_net_hw_enable(pci_dev_t pdev) {
57
uint32_t bar4 = pci_read(pdev, PCI_BAR4);
68
uint32_t bar5 = pci_read(pdev, PCI_BAR5);
@@ -289,7 +291,7 @@ bool virtio_send_packet(void *data, uint16_t len) {
289291

290292
memset(hdr, 0, VNET_HDR_SIZE);
291293

292-
void* pay = kmalloc_aligned(len, 16);
294+
void *pay = buddy_malloc(&tx_buffer_allocator, len);
293295
if (!pay) {
294296
virtq_free_desc(tq, (uint16_t) h);
295297
virtq_free_desc(tq, (uint16_t) p);
@@ -324,7 +326,7 @@ static void vnet_tx_complete(void) {
324326

325327
void* paybuf = (void *) (uintptr_t) tq->desc[pay].addr;
326328
if (paybuf) {
327-
kfree_aligned(paybuf);
329+
buddy_free(&tx_buffer_allocator, paybuf);
328330
}
329331

330332
virtq_free_desc(tq, pay);
@@ -442,6 +444,8 @@ bool EXPORTED MOD_INIT_SYM(KMOD_ABI)(void) {
442444
dprintf("virtio-net: no modern virtio-net device\n");
443445
return false;
444446
}
447+
/* We use a buddy allocator for TX buffer as it is faster and aligned as standard */
448+
buddy_init(&tx_buffer_allocator, 6, 22, 22);
445449
if (!virtio_net_start(&dev)) {
446450
return false;
447451
}

modules/virtio_net/virtio_net.h

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,77 +5,77 @@
55

66
/**
77
* @def VIRTIO_DEVICE_NET_MODERN
8-
* @brief PCI device ID for modern (non-transitional) virtio-net.
8+
* @brief PCI device ID for modern (non-transitional) virtio-net
99
*
10-
* Transitional virtio-net typically reports 0x1000; modern devices use 0x1041.
10+
* Transitional virtio-net typically reports 0x1000; modern devices use 0x1041
1111
*/
1212
#define VIRTIO_DEVICE_NET_MODERN 0x1041
1313

1414
/**
1515
* @def VIRTIO_PCI_CAP_COMMON_CFG
16-
* @brief Vendor capability: common configuration MMIO window selector.
16+
* @brief Vendor capability: common configuration MMIO window selector
1717
*/
1818
#define VIRTIO_PCI_CAP_COMMON_CFG 1
1919
/**
2020
* @def VIRTIO_PCI_CAP_NOTIFY_CFG
21-
* @brief Vendor capability: notify (doorbell) MMIO window selector.
21+
* @brief Vendor capability: notify (doorbell) MMIO window selector
2222
*/
2323
#define VIRTIO_PCI_CAP_NOTIFY_CFG 2
2424
/**
2525
* @def VIRTIO_PCI_CAP_ISR_CFG
26-
* @brief Vendor capability: ISR byte MMIO window selector (legacy/INTx paths).
26+
* @brief Vendor capability: ISR byte MMIO window selector (legacy/INTx paths)
2727
*/
2828
#define VIRTIO_PCI_CAP_ISR_CFG 3
2929
/**
3030
* @def VIRTIO_PCI_CAP_DEVICE_CFG
31-
* @brief Vendor capability: device-specific configuration MMIO window selector.
31+
* @brief Vendor capability: device-specific configuration MMIO window selector
3232
*/
3333
#define VIRTIO_PCI_CAP_DEVICE_CFG 4
3434

3535
/**
3636
* @def VIRTIO_F_VERSION_1
37-
* @brief Feature bit indicating the device speaks modern virtio 1.x.
37+
* @brief Feature bit indicating the device speaks modern virtio 1.x
3838
*
39-
* This lives in the upper 32-bit feature word; keep the constant 64-bit.
39+
* This lives in the upper 32-bit feature word; keep the constant 64-bit
4040
*/
4141
#define VIRTIO_F_VERSION_1 (1ULL << 32)
4242
/**
4343
* @def VIRTIO_NET_F_MAC
44-
* @brief Feature bit: device exposes a fixed MAC address in its config space.
44+
* @brief Feature bit: device exposes a fixed MAC address in its config space
4545
*/
4646
#define VIRTIO_NET_F_MAC (1 << 5)
4747

4848
/**
4949
* @def VIRTQ_DESC_F_NEXT
50-
* @brief Virtqueue descriptor flag: this entry chains to `next`.
50+
* @brief Virtqueue descriptor flag: this entry chains to `next`
5151
*/
5252
#define VIRTQ_DESC_F_NEXT 1
5353
/**
5454
* @def VIRTQ_DESC_F_WRITE
55-
* @brief Virtqueue descriptor flag: device may write to this buffer.
55+
* @brief Virtqueue descriptor flag: device may write to this buffer
5656
*/
5757
#define VIRTQ_DESC_F_WRITE 2
5858

5959
/**
6060
* @def VNET_QSIZE
61-
* @brief Driver’s requested queue size (clamped to device’s `queue_size`).
61+
* @brief Driver’s requested queue size (clamped to device’s `queue_size`)
6262
*/
6363
#define VNET_QSIZE 256
6464
/**
6565
* @def VNET_RX_BUF_SIZE
66-
* @brief Size of each posted RX buffer (must cover virtio header + frame).
66+
* @brief Size of each posted RX buffer (must cover virtio header + frame)
6767
*/
6868
#define VNET_RX_BUF_SIZE 2048
6969
/**
7070
* @def VNET_HDR_SIZE
71-
* @brief Size of the mandatory virtio-net header prepended to each packet.
71+
* @brief Size of the mandatory virtio-net header prepended to each packet
7272
*/
7373
#define VNET_HDR_SIZE (sizeof(virtio_net_hdr_t))
7474

7575
/**
76-
* @brief Device-specific configuration for virtio-net.
76+
* @brief Device-specific configuration for virtio-net
7777
*
78-
* Only the fixed MAC and a status word are consumed by this driver.
78+
* Only the fixed MAC and a status word are consumed by this driver
7979
*/
8080
typedef struct {
8181
/** Station MAC address provided by the device when @ref VIRTIO_NET_F_MAC is set */
@@ -85,11 +85,11 @@ typedef struct {
8585
} __attribute__((packed)) virtio_net_config_t;
8686

8787
/**
88-
* @brief Minimal virtio-net per-packet header (no offloads negotiated).
88+
* @brief Minimal virtio-net per-packet header (no offloads negotiated)
8989
*
90-
* This header precedes every TX and RX payload. All fields are little-endian.
90+
* This header precedes every TX and RX payload. All fields are little-endian
9191
* The driver zero-initialises it; the device may fill some fields on RX when
92-
* certain features are negotiated (not used here).
92+
* certain features are negotiated (not used here)
9393
*/
9494
typedef struct {
9595
/** Flags (eg. checksum present); unused in this minimal driver */
@@ -109,15 +109,15 @@ typedef struct {
109109
} __attribute__((packed)) virtio_net_hdr_t;
110110

111111
/**
112-
* @brief One-byte ISR window (legacy/INTx ack by read-to-clear).
112+
* @brief One-byte ISR window (legacy/INTx ack by read-to-clear)
113113
*/
114114
typedef struct {
115115
/** Interrupt cause byte; reading acknowledges in legacy paths */
116116
volatile uint8_t isr;
117117
} virtio_pci_isr_t;
118118

119119
/**
120-
* @brief In-memory representation of a single virtqueue.
120+
* @brief In-memory representation of a single virtqueue
121121
*/
122122
typedef struct virtq {
123123
/** Queue size (power-of-two), negotiated from device `queue_size` */
@@ -139,7 +139,7 @@ typedef struct virtq {
139139
} virtq_t;
140140

141141
/**
142-
* @brief Driver static state for a single virtio-net instance.
142+
* @brief Driver static state for a single virtio-net instance
143143
*/
144144
static struct {
145145
/** Pointer to the common configuration MMIO window (from caps) */

0 commit comments

Comments
 (0)