From 4cdc802ea38be38edff2b72c9028d7a8af8f8938 Mon Sep 17 00:00:00 2001 From: Manuel Bentele Date: Fri, 20 Nov 2020 07:35:13 +0100 Subject: Add Linux kernel module support for 32-bit architectures (eg. ARM) This change replaces all 64-bit division and modulo operations with specific Linux kernel macros and functions to support 32-bit hardware architectures. Thus, the xloop kernel modules can also run on 32-bit ARM architectures, such as the Raspberry Pi 1 running Raspberry Pi OS. --- README.md | 13 +++++++++++++ src/kernel/xloop_file_fmt_qcow_cache.c | 16 +++++++++++++--- src/kernel/xloop_file_fmt_qcow_main.c | 11 ++++++----- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 8b06805..bd3da5b 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ This repository contains the source code for the xloop Linux kernel modules and the user space utility **xlosetup** to configure xloop devices. The xloop Linux kernel modules can be built for the following Linux kernel versions and Linux distributions: - Archlinux with **Linux kernel 5.9.x** or **5.4.x** + - Raspberry Pi OS with **Linux kernel 5.4.x** - Ubuntu 20.04 with **Linux kernel 5.4.x** - Ubuntu 18.04 with **Linux kernel 4.19.x** - CentOS 8 with **Linux kernel 4.18.x** @@ -34,6 +35,18 @@ pacman -S git \ rpm-tools ``` +#### Raspberry Pi OS with Linux kernel 5.4.x +```shell +apt-get install git \ + make \ + cmake \ + gcc \ + raspberrypi-kernel-headers \ + libcap-dev \ + libncurses-dev \ + rpm +``` + #### Ubuntu 20.04 with Linux kernel 5.4.x ```shell apt-get install git \ diff --git a/src/kernel/xloop_file_fmt_qcow_cache.c b/src/kernel/xloop_file_fmt_qcow_cache.c index 236add5..14f0b75 100644 --- a/src/kernel/xloop_file_fmt_qcow_cache.c +++ b/src/kernel/xloop_file_fmt_qcow_cache.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "xloop_file_fmt_qcow_main.h" #include "xloop_file_fmt_qcow_cache.h" @@ -35,8 +36,14 @@ static inline int __xloop_file_fmt_qcow_cache_get_table_idx( struct xloop_file_fmt_qcow_cache *c, void *table) { ptrdiff_t table_offset = (u8 *) table - (u8 *) c->table_array; - int idx = table_offset / c->table_size; - ASSERT(idx >= 0 && idx < c->size && table_offset % c->table_size == 0); + int idx = div_s64(table_offset, c->table_size); + +#ifdef ASSERT + s32 rem_table_offset_mod_table_size; + div_s64_rem(table_offset, c->table_size, &rem_table_offset_mod_table_size); + ASSERT(idx >= 0 && idx < c->size && rem_table_offset_mod_table_size == 0); +#endif + return idx; } @@ -127,6 +134,7 @@ static int __xloop_file_fmt_qcow_cache_do_get(struct xloop_file_fmt *xlo_fmt, u64 min_lru_counter = U64_MAX; int min_lru_index = -1; u64 read_offset; + u64 offset_div_table_size; size_t len; ASSERT(offset != 0); @@ -139,7 +147,9 @@ static int __xloop_file_fmt_qcow_cache_do_get(struct xloop_file_fmt *xlo_fmt, } /* Check if the table is already cached */ - i = lookup_index = (offset / c->table_size * 4) % c->size; + offset_div_table_size = div_u64(offset, c->table_size) * 4; + div_u64_rem(offset_div_table_size, c->size, &lookup_index); + i = lookup_index; do { const struct xloop_file_fmt_qcow_cache_table *t = &c->entries[i]; diff --git a/src/kernel/xloop_file_fmt_qcow_main.c b/src/kernel/xloop_file_fmt_qcow_main.c index dfde76d..376273d 100644 --- a/src/kernel/xloop_file_fmt_qcow_main.c +++ b/src/kernel/xloop_file_fmt_qcow_main.c @@ -26,6 +26,7 @@ #ifdef CONFIG_ZSTD_DECOMPRESS #include #endif +#include #include @@ -119,7 +120,7 @@ static int __qcow_file_fmt_validate_table(struct xloop_file_fmt *xlo_fmt, { struct xloop_file_fmt_qcow_data *qcow_data = xlo_fmt->private_data; - if (entries > max_size_bytes / entry_len) { + if (entries > div_s64(max_size_bytes, entry_len)) { dev_err(xloop_file_fmt_to_dev(xlo_fmt), "%s too large\n", table_name); return -EFBIG; } @@ -776,7 +777,7 @@ static int qcow_file_fmt_init(struct xloop_file_fmt *xlo_fmt) /* create cache for L2 */ virtual_disk_size = qcow_data->size; - max_l2_entries = DIV_ROUND_UP(virtual_disk_size, qcow_data->cluster_size); + max_l2_entries = DIV64_U64_ROUND_UP(virtual_disk_size, qcow_data->cluster_size); max_l2_cache = round_up( max_l2_entries * xloop_file_fmt_qcow_l2_entry_size(qcow_data), qcow_data->cluster_size); @@ -791,7 +792,7 @@ static int qcow_file_fmt_init(struct xloop_file_fmt *xlo_fmt) l2_cache_entry_size = min(qcow_data->cluster_size, (int)PAGE_SIZE); /* calculate the number of cache tables */ - l2_cache_size /= l2_cache_entry_size; + l2_cache_size = div_u64(l2_cache_size, l2_cache_entry_size); if (l2_cache_size < QCOW_MIN_L2_CACHE_SIZE) { l2_cache_size = QCOW_MIN_L2_CACHE_SIZE; } @@ -802,8 +803,8 @@ static int qcow_file_fmt_init(struct xloop_file_fmt *xlo_fmt) goto free_l1_table; } - qcow_data->l2_slice_size = - l2_cache_entry_size / xloop_file_fmt_qcow_l2_entry_size(qcow_data); + qcow_data->l2_slice_size = div_u64(l2_cache_entry_size, + xloop_file_fmt_qcow_l2_entry_size(qcow_data)); qcow_data->l2_table_cache = xloop_file_fmt_qcow_cache_create(xlo_fmt, l2_cache_size, l2_cache_entry_size); -- cgit v1.2.3-55-g7522