summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManuel Bentele2020-11-20 07:35:13 +0100
committerManuel Bentele2020-11-20 07:35:13 +0100
commit4cdc802ea38be38edff2b72c9028d7a8af8f8938 (patch)
tree827466eeb6cc4e3c97568f9aeff2d59912b791c6
parentAdd upstream and compatibility changes for Linux kernel 5.10 and 4.19 (diff)
downloadxloop-4cdc802ea38be38edff2b72c9028d7a8af8f8938.tar.gz
xloop-4cdc802ea38be38edff2b72c9028d7a8af8f8938.tar.xz
xloop-4cdc802ea38be38edff2b72c9028d7a8af8f8938.zip
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.
-rw-r--r--README.md13
-rw-r--r--src/kernel/xloop_file_fmt_qcow_cache.c16
-rw-r--r--src/kernel/xloop_file_fmt_qcow_main.c11
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 <linux/limits.h>
#include <linux/fs.h>
#include <linux/vmalloc.h>
+#include <linux/math64.h>
#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 <linux/zstd.h>
#endif
+#include <linux/math64.h>
#include <xloop/version.h>
@@ -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);