diff --git a/tools/linux/uio/libuio.c b/tools/linux/uio/libuio.c index c6395c71..b1f60e14 100644 --- a/tools/linux/uio/libuio.c +++ b/tools/linux/uio/libuio.c @@ -65,301 +65,311 @@ static int epoll_fd = -1; */ __attribute__((weak)) int driver_init(int uio_fd, void **maps, uintptr_t *maps_phys, int num_maps, - int argc, char **argv) { - assert(!"UIO driver did not implement driver_init"); - return -1; + int argc, char **argv) +{ + assert(!"UIO driver did not implement driver_init"); + return -1; } -__attribute__((weak)) void driver_notified(int *event_fds, int num_events) { - assert(!"UIO driver did not implement driver_notified"); +__attribute__((weak)) void driver_notified(int *event_fds, int num_events) +{ + assert(!"UIO driver did not implement driver_notified"); } -void uio_irq_enable() { - int32_t one = 1; - int ret = write(main_uio_fd, &one, 4); - if (ret < 0) { - LOG_UIO_ERR("writing 1 to device failed with ret val: %d, errno: %d\n", ret, - errno); - } +void uio_irq_enable() +{ + int32_t one = 1; + int ret = write(main_uio_fd, &one, 4); + if (ret < 0) { + LOG_UIO_ERR("writing 1 to device failed with ret val: %d, errno: %d\n", ret, + errno); + } } -void vmm_notify() { - *(uint8_t *)maps[VMM_NOTIFY_MAP] = 1; - msync(maps[VMM_NOTIFY_MAP], 1, MS_ASYNC); +void vmm_notify() +{ + *(uint8_t *)maps[VMM_NOTIFY_MAP] = 1; + msync(maps[VMM_NOTIFY_MAP], 1, MS_ASYNC); } -void bind_fd_to_event_loop(int fd) { - struct epoll_event sock_event; - sock_event.events = EPOLLIN; - sock_event.data.fd = fd; - if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &sock_event) == -1) { - LOG_UIO_ERR("can't register fd %d to epoll.\n", fd); - exit(1); - } else { - LOG_UIO("registered fd %d to epoll\n", fd); - } +void bind_fd_to_event_loop(int fd) +{ + struct epoll_event sock_event; + sock_event.events = EPOLLIN; + sock_event.data.fd = fd; + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &sock_event) == -1) { + LOG_UIO_ERR("can't register fd %d to epoll.\n", fd); + exit(1); + } else { + LOG_UIO("registered fd %d to epoll\n", fd); + } } -static int create_epoll(void) { - int epoll_fd = epoll_create1(0); - if (epoll_fd == -1) { - LOG_UIO_ERR("can't create the epoll fd.\n"); - exit(1); - } else { - LOG_UIO("created epoll fd %d\n", epoll_fd); - } - return epoll_fd; +static int create_epoll(void) +{ + int epoll_fd = epoll_create1(0); + if (epoll_fd == -1) { + LOG_UIO_ERR("can't create the epoll fd.\n"); + exit(1); + } else { + LOG_UIO("created epoll fd %d\n", epoll_fd); + } + return epoll_fd; } -static int uio_num_maps(int uio_num) { - DIR *dir; - struct dirent *entry; - struct stat statbuf; - regex_t regex; - int count = 0; - - char path[MAX_PATHNAME]; - int len = snprintf(path, sizeof(path), "/sys/class/uio/uio%d/maps", uio_num); - if (len < 0 || len >= sizeof(path)) { - LOG_UIO_ERR("Failed to create maps path string\n"); - exit(1); - } - - /* Compile regex that searches for maps */ - if (regcomp(®ex, "^map[0-9]+$", REG_EXTENDED) != 0) { - LOG_UIO_ERR("Could not compile regex\n"); - exit(1); - } - - dir = opendir(path); - if (dir == NULL) { - LOG_UIO_ERR("Failed to open uio maps directory\n"); - exit(1); - } - - /* Read directory entries */ - while ((entry = readdir(dir)) != NULL) { - char fullPath[MAX_PATHNAME]; - - int len = - snprintf(fullPath, sizeof(fullPath), "%s/%s", path, entry->d_name); - if (len < 0 || len >= sizeof(fullPath)) { - LOG_UIO_ERR("Failed to create full uio maps path\n"); - exit(1); - }; - - /* Check if entry is a directory */ - if (stat(fullPath, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) { - /* Skip over . and .. */ - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { - continue; - } - - /* Check if directory name matches regex */ - if (regexec(®ex, entry->d_name, 0, NULL, 0) == 0) { - count++; - LOG_UIO("Map found: %s\n", entry->d_name); - } +static int uio_num_maps(int uio_num) +{ + DIR *dir; + struct dirent *entry; + struct stat statbuf; + regex_t regex; + int count = 0; + + char path[MAX_PATHNAME]; + int len = snprintf(path, sizeof(path), "/sys/class/uio/uio%d/maps", uio_num); + if (len < 0 || len >= sizeof(path)) { + LOG_UIO_ERR("Failed to create maps path string\n"); + exit(1); } - } - LOG_UIO("Total directories matching 'map[0-9]+': %d\n", count); + /* Compile regex that searches for maps */ + if (regcomp(®ex, "^map[0-9]+$", REG_EXTENDED) != 0) { + LOG_UIO_ERR("Could not compile regex\n"); + exit(1); + } - closedir(dir); - regfree(®ex); + dir = opendir(path); + if (dir == NULL) { + LOG_UIO_ERR("Failed to open uio maps directory\n"); + exit(1); + } - return count; -} + /* Read directory entries */ + while ((entry = readdir(dir)) != NULL) { + char fullPath[MAX_PATHNAME]; + + int len = + snprintf(fullPath, sizeof(fullPath), "%s/%s", path, entry->d_name); + if (len < 0 || len >= sizeof(fullPath)) { + LOG_UIO_ERR("Failed to create full uio maps path\n"); + exit(1); + }; + + /* Check if entry is a directory */ + if (stat(fullPath, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) { + /* Skip over . and .. */ + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + + /* Check if directory name matches regex */ + if (regexec(®ex, entry->d_name, 0, NULL, 0) == 0) { + count++; + LOG_UIO("Map found: %s\n", entry->d_name); + } + } + } + + LOG_UIO("Total directories matching 'map[0-9]+': %d\n", count); -static int uio_map_size(int uio_num, int map_num) { - char path[MAX_PATHNAME]; - char buf[MAX_PATHNAME]; - - int len = snprintf(path, sizeof(path), "/sys/class/uio/uio%d/maps/map%d/size", - uio_num, map_num); - if (len < 0 || len >= sizeof(path)) { - LOG_UIO_ERR("Failed to create uio%d map%d size path string\n", uio_num, - map_num); - exit(1); - } - - int fd = open(path, O_RDONLY); - if (fd < 0) { - LOG_UIO_ERR("Failed to open %s\n", path); - exit(1); - } - ssize_t ret = read(fd, buf, sizeof(buf)); - if (ret < 0) { - LOG_UIO_ERR("Failed to read map%d size\n", map_num); - exit(1); - } - close(fd); - - int size = strtoul(buf, NULL, 0); - if (size == 0 || size == ULONG_MAX) { - LOG_UIO_ERR("Failed to convert map%d size to integer\n", map_num); - exit(1); - } - - return size; + closedir(dir); + regfree(®ex); + + return count; } -static uintptr_t uio_map_addr(int uio_num, int map_num) { - char path[MAX_PATHNAME]; - char buf[MAX_PATHNAME]; - - int len = snprintf(path, sizeof(path), "/sys/class/uio/uio%d/maps/map%d/addr", - uio_num, map_num); - if (len < 0 || len >= sizeof(path)) { - LOG_UIO_ERR("Failed to create uio%d map%d addr path string\n", uio_num, - map_num); - exit(1); - } - - int fd = open(path, O_RDONLY); - if (fd < 0) { - LOG_UIO_ERR("Failed to open %s\n", path); - exit(1); - } - ssize_t ret = read(fd, buf, sizeof(buf)); - if (ret < 0) { - LOG_UIO_ERR("Failed to read map%d addr\n", map_num); - exit(1); - } - close(fd); - - uintptr_t ret_addr = strtoul(buf, NULL, 0); - if (ret_addr == 0 || ret_addr == ULONG_MAX) { - LOG_UIO_ERR("Failed to convert map%d addr to integer\n", map_num); - exit(1); - } - - return ret_addr; +static int uio_map_size(int uio_num, int map_num) +{ + char path[MAX_PATHNAME]; + char buf[MAX_PATHNAME]; + + int len = snprintf(path, sizeof(path), "/sys/class/uio/uio%d/maps/map%d/size", + uio_num, map_num); + if (len < 0 || len >= sizeof(path)) { + LOG_UIO_ERR("Failed to create uio%d map%d size path string\n", uio_num, + map_num); + exit(1); + } + + int fd = open(path, O_RDONLY); + if (fd < 0) { + LOG_UIO_ERR("Failed to open %s\n", path); + exit(1); + } + ssize_t ret = read(fd, buf, sizeof(buf)); + if (ret < 0) { + LOG_UIO_ERR("Failed to read map%d size\n", map_num); + exit(1); + } + close(fd); + + int size = strtoul(buf, NULL, 0); + if (size == 0 || size == ULONG_MAX) { + LOG_UIO_ERR("Failed to convert map%d size to integer\n", map_num); + exit(1); + } + + return size; } -static void uio_map_init(int uio_fd, int uio_num) { - LOG_UIO("Initialising UIO device %d mappings\n", uio_num); - - int curr_num_maps = uio_num_maps(uio_num); - if (curr_num_maps < 0) { - LOG_UIO_ERR("Failed to get number of maps\n"); - exit(1); - } - if (curr_num_maps == 0) { - LOG_UIO_ERR("No maps found\n"); - exit(1); - } - - num_maps += curr_num_maps; - - for (int i = 0; i < curr_num_maps; i++) { - if (curr_map >= UIO_MAX_MAPS) { - LOG_UIO_ERR("too many maps, maximum is %d\n", UIO_MAX_MAPS); - close(uio_fd); - exit(1); +static uintptr_t uio_map_addr(int uio_num, int map_num) +{ + char path[MAX_PATHNAME]; + char buf[MAX_PATHNAME]; + + int len = snprintf(path, sizeof(path), "/sys/class/uio/uio%d/maps/map%d/addr", + uio_num, map_num); + if (len < 0 || len >= sizeof(path)) { + LOG_UIO_ERR("Failed to create uio%d map%d addr path string\n", uio_num, + map_num); + exit(1); + } + + int fd = open(path, O_RDONLY); + if (fd < 0) { + LOG_UIO_ERR("Failed to open %s\n", path); + exit(1); + } + ssize_t ret = read(fd, buf, sizeof(buf)); + if (ret < 0) { + LOG_UIO_ERR("Failed to read map%d addr\n", map_num); + exit(1); } + close(fd); - int size = uio_map_size(uio_num, i); - maps_phys[curr_map] = uio_map_addr(uio_num, i); + uintptr_t ret_addr = strtoul(buf, NULL, 0); + if (ret_addr == 0 || ret_addr == ULONG_MAX) { + LOG_UIO_ERR("Failed to convert map%d addr to integer\n", map_num); + exit(1); + } - if ((maps[curr_map] = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, - uio_fd, i * getpagesize())) == NULL) { - LOG_UIO_ERR("mmap failed, errno: %d\n", errno); - close(uio_fd); - exit(1); + return ret_addr; +} + +static void uio_map_init(int uio_fd, int uio_num) +{ + LOG_UIO("Initialising UIO device %d mappings\n", uio_num); + + int curr_num_maps = uio_num_maps(uio_num); + if (curr_num_maps < 0) { + LOG_UIO_ERR("Failed to get number of maps\n"); + exit(1); + } + if (curr_num_maps == 0) { + LOG_UIO_ERR("No maps found\n"); + exit(1); } - LOG_UIO("mmaped map%d (driver map%d) with 0x%x bytes at %p\n", i, curr_map, - size, maps[curr_map]); + num_maps += curr_num_maps; - curr_map++; - } + for (int i = 0; i < curr_num_maps; i++) { + if (curr_map >= UIO_MAX_MAPS) { + LOG_UIO_ERR("too many maps, maximum is %d\n", UIO_MAX_MAPS); + close(uio_fd); + exit(1); + } + + int size = uio_map_size(uio_num, i); + maps_phys[curr_map] = uio_map_addr(uio_num, i); + + if ((maps[curr_map] = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, + uio_fd, i * getpagesize())) == NULL) { + LOG_UIO_ERR("mmap failed, errno: %d\n", errno); + close(uio_fd); + exit(1); + } + + LOG_UIO("mmaped map%d (driver map%d) with 0x%x bytes at %p\n", i, curr_map, + size, maps[curr_map]); + + curr_map++; + } } int main(int argc, char **argv) { - if (argc < 1) { - printf("Usage: %s [driver_args...]\n", argv[0]); - return 1; - } - - for (int uio_num = 0; uio_num < UIO_MAX_DEV; uio_num++) { - /* Append UIO_NUM to "/dev/uio" to get the full path of the uio device, e.g. - * "/dev/uio0" */ - char uio_device_name[MAX_PATHNAME]; - int len = snprintf(uio_device_name, sizeof(uio_device_name), "/dev/uio%d", - uio_num); - if (len < 0 || len >= sizeof(uio_device_name)) { - LOG_UIO_ERR("Failed to create uio device name string\n"); - return 1; + if (argc < 1) { + printf("Usage: %s [driver_args...]\n", argv[0]); + return 1; } - int uio_fd = open(uio_device_name, O_RDWR); - if (uio_fd < 0) { - LOG_UIO("Failed to open %s\n", uio_device_name); - if (uio_num == MAIN_UIO_NUM) { - LOG_UIO_ERR("Could not open main UIO device, failing\n"); - return 1; - } else { - LOG_UIO("Assuming no more UIO devices\n"); - } - break; + for (int uio_num = 0; uio_num < UIO_MAX_DEV; uio_num++) { + /* Append UIO_NUM to "/dev/uio" to get the full path of the uio device, e.g. + * "/dev/uio0" */ + char uio_device_name[MAX_PATHNAME]; + int len = snprintf(uio_device_name, sizeof(uio_device_name), "/dev/uio%d", + uio_num); + if (len < 0 || len >= sizeof(uio_device_name)) { + LOG_UIO_ERR("Failed to create uio device name string\n"); + return 1; + } + + int uio_fd = open(uio_device_name, O_RDWR); + if (uio_fd < 0) { + LOG_UIO("Failed to open %s\n", uio_device_name); + if (uio_num == MAIN_UIO_NUM) { + LOG_UIO_ERR("Could not open main UIO device, failing\n"); + return 1; + } else { + LOG_UIO("Assuming no more UIO devices\n"); + } + break; + } + + /* Initialise uio device mappings. This reads into /sys/class/uio to + * determine the number of associated devices, their maps and their sizes. + */ + uio_map_init(uio_fd, uio_num); + + /* Set /dev/uio0 as the interrupt */ + if (uio_num == MAIN_UIO_NUM) { + LOG_UIO("Setting main uio device to %s\n", uio_device_name); + main_uio_fd = uio_fd; + } } - /* Initialise uio device mappings. This reads into /sys/class/uio to - * determine the number of associated devices, their maps and their sizes. - */ - uio_map_init(uio_fd, uio_num); + /* Initialise epoll, bind uio fd to it */ + epoll_fd = create_epoll(); + bind_fd_to_event_loop(main_uio_fd); - /* Set /dev/uio0 as the interrupt */ - if (uio_num == MAIN_UIO_NUM) { - LOG_UIO("Setting main uio device to %s\n", uio_device_name); - main_uio_fd = uio_fd; - } - } - - /* Initialise epoll, bind uio fd to it */ - epoll_fd = create_epoll(); - bind_fd_to_event_loop(main_uio_fd); - - /* Initialise driver, we pass the UIO device mappings to the driver, - * skipping the first one which only contains UIO's irq status, and - * the second one which contains the uio notify region. - */ - LOG_UIO("Initialising driver with %d driver specific maps\n", num_maps - 2); - if (driver_init(main_uio_fd, maps + 2, maps_phys + 2, num_maps - 2, argc - 1, - argv + 1) != 0) { - LOG_UIO_ERR("Failed to initialise driver\n"); - exit(1); - } - - /* Enable uio interrupt */ - uio_irq_enable(); - - struct epoll_event events[MAX_EVENTS]; - int event_fds[MAX_EVENTS]; - while (true) { - int nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); - if (nfds == -1) { - LOG_UIO_ERR("epoll_wait failed, errno: %d\n", errno); - exit(1); + /* Initialise driver, we pass the UIO device mappings to the driver, + * skipping the first one which only contains UIO's irq status, and + * the second one which contains the uio notify region. + */ + LOG_UIO("Initialising driver with %d driver specific maps\n", num_maps - 2); + if (driver_init(main_uio_fd, maps + 2, maps_phys + 2, num_maps - 2, argc - 1, + argv + 1) != 0) { + LOG_UIO_ERR("Failed to initialise driver\n"); + exit(1); } - for (int n = 0; n < nfds; n++) { - event_fds[n] = events[n].data.fd; - if (event_fds[n] == main_uio_fd) { - int irq_count; - int read_ret = read(main_uio_fd, &irq_count, sizeof(irq_count)); - _unused(read_ret); - assert(read_ret >= 0); - LOG_UIO("received irq, count: %d\n", irq_count); - } + /* Enable uio interrupt */ + uio_irq_enable(); + + struct epoll_event events[MAX_EVENTS]; + int event_fds[MAX_EVENTS]; + while (true) { + int nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); + if (nfds == -1) { + LOG_UIO_ERR("epoll_wait failed, errno: %d\n", errno); + exit(1); + } + + for (int n = 0; n < nfds; n++) { + event_fds[n] = events[n].data.fd; + if (event_fds[n] == main_uio_fd) { + int irq_count; + int read_ret = read(main_uio_fd, &irq_count, sizeof(irq_count)); + _unused(read_ret); + assert(read_ret >= 0); + LOG_UIO("received irq, count: %d\n", irq_count); + } + } + + /* wake the guest driver up to do some real works */ + driver_notified(event_fds, nfds); } - /* wake the guest driver up to do some real works */ - driver_notified(event_fds, nfds); - } - - return 0; + return 0; } diff --git a/tools/linux/uio_drivers/blk/blk.c b/tools/linux/uio_drivers/blk/blk.c index 21ee83e0..9a8081a1 100644 --- a/tools/linux/uio_drivers/blk/blk.c +++ b/tools/linux/uio_drivers/blk/blk.c @@ -49,243 +49,246 @@ uintptr_t blk_client_data_phys[BLK_NUM_CLIENTS + 1]; size_t blk_client_data_size[BLK_NUM_CLIENTS + 1]; int driver_init(int uio_fd, void **maps, uintptr_t *maps_phys, int num_maps, - int argc, char **argv) { - LOG_UIO_BLOCK("Initialising...\n"); - - /* Expects a storage_info map, request queue map, response queue map, virt - * data map, and BLK_NUM_CLIENT data mappings. - */ - if (num_maps != BLK_NUM_CLIENTS + 5) { - LOG_UIO_BLOCK_ERR("Expecting %d maps, got %d\n", BLK_NUM_CLIENTS + 5, - num_maps); - return -1; - } - - if (argc != 1) { - LOG_UIO_BLOCK_ERR("Expecting 1 driver argument, got %d\n", argc); - return -1; - } - - char *storage_path = argv[0]; - - driver_blk_vmm_info_passing_t *vmm_info_passing = - (driver_blk_vmm_info_passing_t *)maps[0]; - blk_storage_info = (blk_storage_info_t *)maps[1]; - blk_req_queue_t *req_queue = (blk_req_queue_t *)maps[2]; - blk_resp_queue_t *resp_queue = (blk_resp_queue_t *)maps[3]; - for (int i = 0; i < BLK_NUM_CLIENTS + 1; i++) { - blk_client_data[i] = (uintptr_t)maps[4 + i]; - blk_client_data_phys[i] = vmm_info_passing->client_data_phys[i]; - blk_client_data_size[i] = vmm_info_passing->client_data_size[i]; - } - - LOG_UIO_BLOCK( - "Storage info phys addr: 0x%lx, Request queue phys addr: 0x%lx, " - "Response queue phys addr: 0x%lx\n", - maps_phys[1], maps_phys[2], maps_phys[3]); + int argc, char **argv) +{ + LOG_UIO_BLOCK("Initialising...\n"); + + /* Expects a storage_info map, request queue map, response queue map, virt + * data map, and BLK_NUM_CLIENT data mappings. + */ + if (num_maps != BLK_NUM_CLIENTS + 5) { + LOG_UIO_BLOCK_ERR("Expecting %d maps, got %d\n", BLK_NUM_CLIENTS + 5, + num_maps); + return -1; + } + + if (argc != 1) { + LOG_UIO_BLOCK_ERR("Expecting 1 driver argument, got %d\n", argc); + return -1; + } + + char *storage_path = argv[0]; + + driver_blk_vmm_info_passing_t *vmm_info_passing = + (driver_blk_vmm_info_passing_t *)maps[0]; + blk_storage_info = (blk_storage_info_t *)maps[1]; + blk_req_queue_t *req_queue = (blk_req_queue_t *)maps[2]; + blk_resp_queue_t *resp_queue = (blk_resp_queue_t *)maps[3]; + for (int i = 0; i < BLK_NUM_CLIENTS + 1; i++) { + blk_client_data[i] = (uintptr_t)maps[4 + i]; + blk_client_data_phys[i] = vmm_info_passing->client_data_phys[i]; + blk_client_data_size[i] = vmm_info_passing->client_data_size[i]; + } + + LOG_UIO_BLOCK( + "Storage info phys addr: 0x%lx, Request queue phys addr: 0x%lx, " + "Response queue phys addr: 0x%lx\n", + maps_phys[1], maps_phys[2], maps_phys[3]); #ifdef DEBUG_UIO_BLOCK - LOG_UIO_BLOCK("Virt data io addr, Virt data size:\n"); - printf(" 0x%lx, 0x%lx\n", blk_client_data_phys[0], - blk_client_data_size[0]); - LOG_UIO_BLOCK("Client data io addr, Client data size:\n"); - for (int i = 1; i < BLK_NUM_CLIENTS + 1; i++) { - printf(" client %i: 0x%lx, 0x%lx\n", i, blk_client_data_phys[i], - blk_client_data_size[i]); - } + LOG_UIO_BLOCK("Virt data io addr, Virt data size:\n"); + printf(" 0x%lx, 0x%lx\n", blk_client_data_phys[0], + blk_client_data_size[0]); + LOG_UIO_BLOCK("Client data io addr, Client data size:\n"); + for (int i = 1; i < BLK_NUM_CLIENTS + 1; i++) { + printf(" client %i: 0x%lx, 0x%lx\n", i, blk_client_data_phys[i], + blk_client_data_size[i]); + } #endif - blk_queue_init(&h, req_queue, resp_queue, BLK_QUEUE_CAPACITY_DRIV); - - storage_fd = open(storage_path, O_RDWR); - if (storage_fd < 0) { - LOG_UIO_BLOCK_ERR("Failed to open storage driver: %s\n", strerror(errno)); - return -1; - } - LOG_UIO_BLOCK("Opened storage drive: %s\n", storage_path); - - struct stat storageStat; - if (fstat(storage_fd, &storageStat) < 0) { - LOG_UIO_BLOCK_ERR("Failed to get storage drive status: %s\n", - strerror(errno)); - return -1; - } - - if (!S_ISBLK(storageStat.st_mode)) { - LOG_UIO_BLOCK_ERR("Storage drive is of an unsupported type\n"); - return -1; - } - - /* Set drive as read-write */ - int read_only_set = 0; - if (ioctl(storage_fd, BLKROSET, &read_only_set) == -1) { - LOG_UIO_BLOCK_ERR("Failed to set storage drive as read-write: %s\n", - strerror(errno)); - return -1; - } - - /* Get read only status */ - int read_only; - if (ioctl(storage_fd, BLKROGET, &read_only) == -1) { - LOG_UIO_BLOCK_ERR("Failed to get storage drive read only status: %s\n", - strerror(errno)); - return -1; - } - blk_storage_info->read_only = (bool)read_only; - - /* Get logical sector size */ - int sector_size; - if (ioctl(storage_fd, BLKSSZGET, §or_size) == -1) { - LOG_UIO_BLOCK_ERR("Failed to get storage drive sector size: %s\n", - strerror(errno)); - return -1; - } - blk_storage_info->sector_size = (uint16_t)sector_size; - - /* Get size */ - uint64_t size; - if (ioctl(storage_fd, BLKGETSIZE64, &size) == -1) { - LOG_UIO_BLOCK_ERR("Failed to get storage drive size: %s\n", - strerror(errno)); - return -1; - } - blk_storage_info->capacity = size / BLK_TRANSFER_SIZE; - - LOG_UIO_BLOCK("Raw block device: read_only=%d, sector_size=%d, " - "capacity(sectors)=%ld\n", - (int)blk_storage_info->read_only, blk_storage_info->sector_size, - blk_storage_info->capacity); - - /* Optimal size */ - /* As far as I know linux does not let you query this from userspace, set as 0 - * to mean undefined */ - blk_storage_info->block_size = 0; - - /* Driver is ready to go, set ready in shared storage info page */ - __atomic_store_n(&blk_storage_info->ready, true, __ATOMIC_RELEASE); - - LOG_UIO_BLOCK("Driver initialized\n"); - - return 0; + blk_queue_init(&h, req_queue, resp_queue, BLK_QUEUE_CAPACITY_DRIV); + + storage_fd = open(storage_path, O_RDWR); + if (storage_fd < 0) { + LOG_UIO_BLOCK_ERR("Failed to open storage driver: %s\n", strerror(errno)); + return -1; + } + LOG_UIO_BLOCK("Opened storage drive: %s\n", storage_path); + + struct stat storageStat; + if (fstat(storage_fd, &storageStat) < 0) { + LOG_UIO_BLOCK_ERR("Failed to get storage drive status: %s\n", + strerror(errno)); + return -1; + } + + if (!S_ISBLK(storageStat.st_mode)) { + LOG_UIO_BLOCK_ERR("Storage drive is of an unsupported type\n"); + return -1; + } + + /* Set drive as read-write */ + int read_only_set = 0; + if (ioctl(storage_fd, BLKROSET, &read_only_set) == -1) { + LOG_UIO_BLOCK_ERR("Failed to set storage drive as read-write: %s\n", + strerror(errno)); + return -1; + } + + /* Get read only status */ + int read_only; + if (ioctl(storage_fd, BLKROGET, &read_only) == -1) { + LOG_UIO_BLOCK_ERR("Failed to get storage drive read only status: %s\n", + strerror(errno)); + return -1; + } + blk_storage_info->read_only = (bool)read_only; + + /* Get logical sector size */ + int sector_size; + if (ioctl(storage_fd, BLKSSZGET, §or_size) == -1) { + LOG_UIO_BLOCK_ERR("Failed to get storage drive sector size: %s\n", + strerror(errno)); + return -1; + } + blk_storage_info->sector_size = (uint16_t)sector_size; + + /* Get size */ + uint64_t size; + if (ioctl(storage_fd, BLKGETSIZE64, &size) == -1) { + LOG_UIO_BLOCK_ERR("Failed to get storage drive size: %s\n", + strerror(errno)); + return -1; + } + blk_storage_info->capacity = size / BLK_TRANSFER_SIZE; + + LOG_UIO_BLOCK("Raw block device: read_only=%d, sector_size=%d, " + "capacity(sectors)=%ld\n", + (int)blk_storage_info->read_only, blk_storage_info->sector_size, + blk_storage_info->capacity); + + /* Optimal size */ + /* As far as I know linux does not let you query this from userspace, set as 0 + * to mean undefined */ + blk_storage_info->block_size = 0; + + /* Driver is ready to go, set ready in shared storage info page */ + __atomic_store_n(&blk_storage_info->ready, true, __ATOMIC_RELEASE); + + LOG_UIO_BLOCK("Driver initialized\n"); + + return 0; } /* The virtualiser gives us an io address. We need to figure out which uio * mapping this corresponds to, so that we can fetch the corresponding mmaped * virt address. */ -static inline uintptr_t io_to_virt(uintptr_t io_addr) { - for (int i = 0; i < BLK_NUM_CLIENTS + 1; i++) { - if (io_addr - blk_client_data_phys[i] < blk_client_data_size[i]) { - LOG_UIO_BLOCK("io address 0x%lx corresponds to client %d\n", io_addr, i); - return blk_client_data[i] + (io_addr - blk_client_data_phys[i]); +static inline uintptr_t io_to_virt(uintptr_t io_addr) +{ + for (int i = 0; i < BLK_NUM_CLIENTS + 1; i++) { + if (io_addr - blk_client_data_phys[i] < blk_client_data_size[i]) { + LOG_UIO_BLOCK("io address 0x%lx corresponds to client %d\n", io_addr, i); + return blk_client_data[i] + (io_addr - blk_client_data_phys[i]); + } } - } - /* Didn't find a match */ - assert(false); - return 0; + /* Didn't find a match */ + assert(false); + return 0; } -void driver_notified(int *events_fds, int num_events) { - int err = 0; - _unused(err); - blk_req_code_t req_code; - uintptr_t req_io; - uint32_t req_block_number; - uint16_t req_count; - uint32_t req_id; - - while (!blk_queue_empty_req(&h)) { - err = blk_dequeue_req(&h, &req_code, &req_io, &req_block_number, &req_count, - &req_id); - assert(!err); - LOG_UIO_BLOCK("Received request: code=%d, io=0x%lx, block_number=%d, " - "count=%d, id=%d\n", - req_code, req_io, req_block_number, req_count, req_id); - - blk_resp_status_t status = BLK_RESP_OK; - uint16_t success_count = 0; - - switch (req_code) { - case BLK_REQ_READ: { - int ret = lseek(storage_fd, (off_t)req_block_number * BLK_TRANSFER_SIZE, - SEEK_SET); - if (ret < 0) { - LOG_UIO_BLOCK_ERR("Failed to seek in storage: %s\n", strerror(errno)); - status = BLK_RESP_ERR_UNSPEC; - success_count = 0; - break; - } - LOG_UIO_BLOCK("Reading from storage\n"); - - int bytes_read = read(storage_fd, (void *)io_to_virt(req_io), - req_count * BLK_TRANSFER_SIZE); - LOG_UIO_BLOCK("Read from storage successfully: %d bytes\n", bytes_read); - if (bytes_read < 0) { - LOG_UIO_BLOCK_ERR("Failed to read from storage: %s\n", strerror(errno)); - status = BLK_RESP_ERR_UNSPEC; - success_count = 0; - } else { - status = BLK_RESP_OK; - success_count = bytes_read / BLK_TRANSFER_SIZE; - } - break; - } - case BLK_REQ_WRITE: { - int ret = lseek(storage_fd, (off_t)req_block_number * BLK_TRANSFER_SIZE, - SEEK_SET); - if (ret < 0) { - LOG_UIO_BLOCK_ERR("Failed to seek in storage: %s\n", strerror(errno)); - status = BLK_RESP_ERR_UNSPEC; - success_count = 0; - break; - } - LOG_UIO_BLOCK("Writing to storage\n"); - int bytes_written = write(storage_fd, (void *)io_to_virt(req_io), - req_count * BLK_TRANSFER_SIZE); - LOG_UIO_BLOCK("Wrote to storage successfully: %d bytes\n", bytes_written); - if (bytes_written < 0) { - LOG_UIO_BLOCK_ERR("Failed to write to storage: %s\n", strerror(errno)); - status = BLK_RESP_ERR_UNSPEC; - success_count = 0; - } else { - status = BLK_RESP_OK; - success_count = bytes_written / BLK_TRANSFER_SIZE; - } - break; - } - case BLK_REQ_FLUSH: { - int ret = fsync(storage_fd); - if (ret != 0) { - LOG_UIO_BLOCK_ERR("Failed to flush storage: %s\n", strerror(errno)); - status = BLK_RESP_ERR_UNSPEC; - } else { - status = BLK_RESP_OK; - } - break; +void driver_notified(int *events_fds, int num_events) +{ + int err = 0; + _unused(err); + blk_req_code_t req_code; + uintptr_t req_io; + uint32_t req_block_number; + uint16_t req_count; + uint32_t req_id; + + while (!blk_queue_empty_req(&h)) { + err = blk_dequeue_req(&h, &req_code, &req_io, &req_block_number, &req_count, + &req_id); + assert(!err); + LOG_UIO_BLOCK("Received request: code=%d, io=0x%lx, block_number=%d, " + "count=%d, id=%d\n", + req_code, req_io, req_block_number, req_count, req_id); + + blk_resp_status_t status = BLK_RESP_OK; + uint16_t success_count = 0; + + switch (req_code) { + case BLK_REQ_READ: { + int ret = lseek(storage_fd, (off_t)req_block_number * BLK_TRANSFER_SIZE, + SEEK_SET); + if (ret < 0) { + LOG_UIO_BLOCK_ERR("Failed to seek in storage: %s\n", strerror(errno)); + status = BLK_RESP_ERR_UNSPEC; + success_count = 0; + break; + } + LOG_UIO_BLOCK("Reading from storage\n"); + + int bytes_read = read(storage_fd, (void *)io_to_virt(req_io), + req_count * BLK_TRANSFER_SIZE); + LOG_UIO_BLOCK("Read from storage successfully: %d bytes\n", bytes_read); + if (bytes_read < 0) { + LOG_UIO_BLOCK_ERR("Failed to read from storage: %s\n", strerror(errno)); + status = BLK_RESP_ERR_UNSPEC; + success_count = 0; + } else { + status = BLK_RESP_OK; + success_count = bytes_read / BLK_TRANSFER_SIZE; + } + break; + } + case BLK_REQ_WRITE: { + int ret = lseek(storage_fd, (off_t)req_block_number * BLK_TRANSFER_SIZE, + SEEK_SET); + if (ret < 0) { + LOG_UIO_BLOCK_ERR("Failed to seek in storage: %s\n", strerror(errno)); + status = BLK_RESP_ERR_UNSPEC; + success_count = 0; + break; + } + LOG_UIO_BLOCK("Writing to storage\n"); + int bytes_written = write(storage_fd, (void *)io_to_virt(req_io), + req_count * BLK_TRANSFER_SIZE); + LOG_UIO_BLOCK("Wrote to storage successfully: %d bytes\n", bytes_written); + if (bytes_written < 0) { + LOG_UIO_BLOCK_ERR("Failed to write to storage: %s\n", strerror(errno)); + status = BLK_RESP_ERR_UNSPEC; + success_count = 0; + } else { + status = BLK_RESP_OK; + success_count = bytes_written / BLK_TRANSFER_SIZE; + } + break; + } + case BLK_REQ_FLUSH: { + int ret = fsync(storage_fd); + if (ret != 0) { + LOG_UIO_BLOCK_ERR("Failed to flush storage: %s\n", strerror(errno)); + status = BLK_RESP_ERR_UNSPEC; + } else { + status = BLK_RESP_OK; + } + break; + } + case BLK_REQ_BARRIER: { + int ret = fsync(storage_fd); + if (ret != 0) { + LOG_UIO_BLOCK_ERR("Failed to flush storage: %s\n", strerror(errno)); + status = BLK_RESP_ERR_UNSPEC; + } else { + status = BLK_RESP_OK; + } + break; + } + default: + LOG_UIO_BLOCK_ERR("Unknown command code: %d\n", req_code); + assert(false); + } + /* Response queue is never full if number of inflight requests <= response + * queue capacity */ + err = blk_enqueue_resp(&h, status, success_count, req_id); + assert(!err); + LOG_UIO_BLOCK("Enqueued response: status=%d, success_count=%d, id=%d\n", + status, success_count, req_id); } - case BLK_REQ_BARRIER: { - int ret = fsync(storage_fd); - if (ret != 0) { - LOG_UIO_BLOCK_ERR("Failed to flush storage: %s\n", strerror(errno)); - status = BLK_RESP_ERR_UNSPEC; - } else { - status = BLK_RESP_OK; - } - break; - } - default: - LOG_UIO_BLOCK_ERR("Unknown command code: %d\n", req_code); - assert(false); - } - /* Response queue is never full if number of inflight requests <= response - * queue capacity */ - err = blk_enqueue_resp(&h, status, success_count, req_id); - assert(!err); - LOG_UIO_BLOCK("Enqueued response: status=%d, success_count=%d, id=%d\n", - status, success_count, req_id); - } - - uio_irq_enable(); - vmm_notify(); - LOG_UIO_BLOCK("Notified other side\n"); + + uio_irq_enable(); + vmm_notify(); + LOG_UIO_BLOCK("Notified other side\n"); }