Skip to content

Commit e7c5da0

Browse files
authored
Merge pull request #7 from arceos-hypervisor/bqs
Enhance IVC framework with multi-publisher support and refactor
2 parents d626890 + 8f907f3 commit e7c5da0

25 files changed

Lines changed: 2198 additions & 43 deletions

.clang-format

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
BasedOnStyle: LLVM,
3+
UseTab: Always,
4+
IndentWidth: 4,
5+
TabWidth: 4,
6+
AlignAfterOpenBracket: AlwaysBreak,
7+
BreakBeforeBraces: Allman,
8+
# AllowShortIfStatementsOnASingleLine: false,
9+
# IndentCaseLabels: false,
10+
# ColumnLimit: 0,
11+
# AccessModifierOffset: -4,
12+
# NamespaceIndentation: All,
13+
# FixNamespaceComments: false
14+
}

arceos-driver/main.c

Lines changed: 0 additions & 43 deletions
This file was deleted.

ivc/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
build/

ivc/Makefile

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Makefile for building components of the IVC (Inter-VM Communication) library: kernel driver, user
2+
# library, python bindings, and demo applications.
3+
4+
# Basic information
5+
LIB_NAME := ivc
6+
7+
# Architecture and cross-compilation settings
8+
ARCH ?= arm64
9+
CROSS ?= aarch64-linux-musl-
10+
CCOMP ?= $(CROSS)gcc
11+
CAR ?= $(CROSS)ar
12+
13+
# Input, output, and kernel dependency directories
14+
MAKEFILE_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
15+
16+
BUILD_DIR ?= $(MAKEFILE_DIR)build
17+
INCLUDE_DIR := $(MAKEFILE_DIR)include
18+
19+
ULIB_SRC_DIR := $(MAKEFILE_DIR)ulib
20+
DEMO_SRC_DIR := $(MAKEFILE_DIR)demo
21+
22+
# Source files and outputs
23+
ULIB_SRC := $(wildcard $(ULIB_SRC_DIR)/*.c)
24+
ULIB_OBJ := $(patsubst $(ULIB_SRC_DIR)/%.c,$(BUILD_DIR)/ulib/%.o,$(ULIB_SRC))
25+
ULIB_STATIC := $(BUILD_DIR)/lib$(LIB_NAME).a
26+
ULIB_SHARED := $(BUILD_DIR)/lib$(LIB_NAME).so
27+
28+
DEMO_SRC := $(wildcard $(DEMO_SRC_DIR)/*.c)
29+
DEMO_BIN := $(patsubst $(DEMO_SRC_DIR)/%.c,$(BUILD_DIR)/demo/%, $(DEMO_SRC))
30+
31+
32+
# Compiler flags
33+
CFLAGS ?= -I$(INCLUDE_DIR)
34+
ULIB_CFLAGS ?= $(CFLAGS) -Wall -Wextra -Os -s -Wl,--gc-sections -fPIC
35+
DEMO_CFLAGS ?= $(CFLAGS) -Wall -Wextra -Os -s -Wl,--gc-sections -static
36+
37+
.PHONY: all ulib demo output_dir clean rebuild
38+
all: ulib demo
39+
40+
ulib: output_dir $(ULIB_STATIC) $(ULIB_SHARED)
41+
demo: output_dir $(DEMO_BIN)
42+
43+
$(ULIB_STATIC): $(ULIB_OBJ)
44+
$(CAR) rcs $@ $^
45+
46+
$(ULIB_SHARED): $(ULIB_OBJ)
47+
$(CCOMP) -shared -o $@ $^
48+
49+
$(BUILD_DIR)/ulib/%.o: $(ULIB_SRC_DIR)/%.c
50+
$(CCOMP) $(ULIB_CFLAGS) -c $< -o $@
51+
52+
$(BUILD_DIR)/demo/%: $(DEMO_SRC_DIR)/%.c $(ULIB_STATIC)
53+
$(CCOMP) $(DEMO_CFLAGS) -o $@ $< -L$(BUILD_DIR) -l$(LIB_NAME)
54+
55+
output_dir:
56+
@mkdir -p $(BUILD_DIR)/ulib
57+
@mkdir -p $(BUILD_DIR)/demo
58+
59+
clean:
60+
rm -rf $(BUILD_DIR)
61+
62+
rebuild: clean all

ivc/demo/publish.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include <ivc/ulib.h>
2+
#include <stdio.h>
3+
#include <string.h>
4+
#include <stdlib.h>
5+
6+
char message[1024];
7+
int main(int argc, char *argv[]) {
8+
if (argc != 2) {
9+
fprintf(stderr, "Usage: %s <channel_key>\n", argv[0]);
10+
return 1;
11+
}
12+
uint64_t channel_key = strtoull(argv[1], NULL, 0);
13+
14+
int ret = 0;
15+
16+
ivc_manager_p manager = ivc_open_manager();
17+
if (!manager) {
18+
fprintf(stderr, "Failed to open IVC manager\n");
19+
return 1;
20+
}
21+
22+
ivc_publisher_p publisher = ivc_publish(manager, channel_key, 16 * 1024);
23+
if (!publisher) {
24+
fprintf(stderr, "Failed to publish channel\n");
25+
ret = 2;
26+
goto close_manager;
27+
}
28+
29+
while (scanf("%1023s", message) == 1) {
30+
if (ivc_write_all(publisher, message, strlen(message)) < 0) {
31+
fprintf(stderr, "Failed to write to publisher\n");
32+
ret = 3;
33+
break;
34+
}
35+
printf("Published: %s, total published: %lu\n", message, publisher->write);
36+
}
37+
38+
if (ivc_unpublish(publisher) < 0) {
39+
fprintf(stderr, "Failed to unpublish publisher\n");
40+
ret = 4;
41+
}
42+
close_manager:
43+
if (ivc_close_manager(manager) < 0) {
44+
fprintf(stderr, "Failed to close IVC manager\n");
45+
ret = 5;
46+
}
47+
printf("IVC publisher example finished.\n");
48+
return ret;
49+
}

ivc/demo/subscribe.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include <ivc/ulib.h>
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <unistd.h>
5+
6+
char message[1024];
7+
int main(int argc, char *argv[]) {
8+
unsigned long target_count = 5;
9+
unsigned long received = 0;
10+
unsigned long empty_polls = 0;
11+
12+
if (argc != 3 && argc != 4) {
13+
fprintf(stderr, "Usage: %s <target_publisher_id> <channel_key> [message_count]\n", argv[0]);
14+
return 1;
15+
}
16+
uint64_t target_publisher_id = strtoull(argv[1], NULL, 0);
17+
uint64_t channel_key = strtoull(argv[2], NULL, 0);
18+
if (argc == 4) {
19+
target_count = strtoul(argv[3], NULL, 0);
20+
}
21+
22+
int ret = 0;
23+
24+
ivc_manager_p manager = ivc_open_manager();
25+
if (!manager) {
26+
fprintf(stderr, "Failed to open IVC manager\n");
27+
return 1;
28+
}
29+
30+
ivc_subscriber_p subscriber = ivc_subscribe(manager, target_publisher_id, channel_key);
31+
if (!subscriber) {
32+
fprintf(stderr, "Failed to subscribe to channel\n");
33+
ret = 2;
34+
goto close_manager;
35+
}
36+
37+
while (received < target_count) {
38+
int bytes_read = ivc_read(subscriber, message, sizeof(message) - 1);
39+
if (bytes_read < 0) {
40+
fprintf(stderr, "Failed to read from subscriber\n");
41+
ret = 2;
42+
break;
43+
} else if (bytes_read == 0) {
44+
if (++empty_polls > 200000) {
45+
fprintf(stderr, "Timed out waiting for IVC messages\n");
46+
ret = 5;
47+
break;
48+
}
49+
usleep(10000);
50+
} else {
51+
message[bytes_read] = '\0'; // Null-terminate the string
52+
received++;
53+
empty_polls = 0;
54+
printf("linux ivc recv %lu/%lu: %s\n", received, target_count, message);
55+
}
56+
}
57+
if (ret == 0) {
58+
printf("linux ivc demo pass\n");
59+
}
60+
61+
if (ivc_unsubscribe(subscriber) < 0) {
62+
fprintf(stderr, "Failed to unsubscribe from channel\n");
63+
ret = 3;
64+
}
65+
close_manager:
66+
if (ivc_close_manager(manager) < 0) {
67+
fprintf(stderr, "Failed to close IVC manager\n");
68+
ret = 4;
69+
}
70+
printf("IVC subscriber example finished.\n");
71+
return ret;
72+
}

ivc/include/ivc/ioctl_args.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#pragma once
2+
3+
#include "./ivc_dev.h"
4+
5+
#ifndef __KERNEL__
6+
# include <sys/ioctl.h>
7+
# include <stdint.h>
8+
#endif
9+
10+
typedef struct ivc_publish_arg {
11+
uint64_t channel_key; // Unique key for the channel
12+
uint64_t channel_size; // Size of the channel in bytes
13+
char device_name[MAX_IVC_DEV_NAME_LENGTH]; // Returns the device name for the channel
14+
} ivc_publish_arg_t, *ivc_publish_arg_p;
15+
16+
typedef struct ivc_subscribe_arg {
17+
uint64_t target_publisher_id; // ID of the publisher to subscribe to (VM ID is used as for now)
18+
uint64_t channel_key; // Key of the channel to subscribe to
19+
char device_name[MAX_IVC_DEV_NAME_LENGTH]; // Returns the device name for the channel
20+
} ivc_subscribe_arg_t, *ivc_subscribe_arg_p;
21+
22+
#define IVC_PUBLISH_CHANNEL _IOW(0, 0, ivc_publish_arg_t)
23+
#define IVC_UNPUBLISH_CHANNEL _IOW(0, 1, ivc_publish_arg_t)
24+
#define IVC_SUBSCRIBE_CHANNEL _IOW(0, 2, ivc_subscribe_arg_t)
25+
#define IVC_UNSUBSCRIBE_CHANNEL _IOW(0, 3, ivc_subscribe_arg_t)

ivc/include/ivc/ivc_dev.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
3+
#define IVC_DEV_NAME "axivc"
4+
5+
#define IVC_PUBLISHER_DEV_NAME_PREFIX "axivc_publisher_"
6+
#define IVC_SUBSCRIBER_DEV_NAME_PREFIX "axivc_subscriber_"
7+
8+
#define MAX_IVC_DEV_NAME_LENGTH 64
9+
10+
#define DEV_PATH_PREFIX "/dev/"
11+
#define IVC_DEV_PATH (DEV_PATH_PREFIX IVC_DEV_NAME)

ivc/include/ivc/ulib.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#pragma once
2+
3+
#include "./ioctl_args.h"
4+
5+
#include <stdio.h>
6+
#include <stddef.h>
7+
8+
#ifdef __cplusplus
9+
extern "C" {
10+
#endif
11+
12+
// TODO: record publishers and subscribers created and recycle them when close the IVC manager.
13+
typedef struct ivc_manager {
14+
int64_t fd; // File descriptor for the IVC device
15+
} ivc_manager_t, *ivc_manager_p;
16+
17+
ivc_manager_p ivc_open_manager(void);
18+
int ivc_close_manager(ivc_manager_p manager);
19+
20+
21+
typedef struct ivc_subscriber {
22+
ivc_manager_p manager; // Pointer to the IVC manager
23+
ivc_subscribe_arg_t subscribe_arg; // Subscription argument structure
24+
int64_t fd; // File descriptor for the subscriber's device
25+
uint64_t read; // Number of bytes read from the channel
26+
} ivc_subscriber_t, *ivc_subscriber_p;
27+
28+
ivc_subscriber_p ivc_subscribe(ivc_manager_p manager, uint64_t publisher_id, uint64_t channel_key);
29+
int ivc_read(ivc_subscriber_p subscriber, void *buf, size_t count);
30+
int ivc_unsubscribe(ivc_subscriber_p subscriber);
31+
32+
33+
typedef struct ivc_publisher {
34+
ivc_manager_p manager; // Pointer to the IVC manager
35+
ivc_publish_arg_t publish_arg; // Publish argument structure
36+
int64_t fd; // File descriptor for the publisher's device
37+
uint64_t write; // Number of bytes written to the channel
38+
} ivc_publisher_t, *ivc_publisher_p;
39+
40+
ivc_publisher_p ivc_publish(ivc_manager_p manager, uint64_t channel_key, uint64_t channel_size);
41+
int ivc_write(ivc_publisher_p publisher, const void *buf, size_t count);
42+
int ivc_write_all(ivc_publisher_p publisher, const void *buf, size_t count);
43+
int ivc_unpublish(ivc_publisher_p publisher);
44+
45+
#ifdef __cplusplus
46+
}
47+
#endif

ivc/kernel_driver/.gitignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
bin
2+
modules
3+
.tmp_versions
4+
.vscode
5+
__pycache__
6+
7+
*.so
8+
*.ko
9+
*.mod
10+
*.o
11+
*.d
12+
*.cmd
13+
*.d
14+
**/Module.*
15+
**/modules.*
16+
*_wrap.c
17+
**/*.dat
18+
*.mod.c

0 commit comments

Comments
 (0)