diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f333e761d5568ba256c3d5c48a2c6dfd6f4660b5..376bd38b62941d53255d67be154f1ad64f85732b 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -188,11 +188,11 @@ riscv64:
   image: i10git.cs.fau.de:5005/pycodegen/pycodegen/riscv64
   variables:
     PYSTENCILS_SIMD: "rvv"
-    QEMU_CPU: "rv64,v=true"
+    QEMU_CPU: "rv64,v=true,zicboz=true"
   before_script:
     - *multiarch_before_script
-    - sed -i 's/march=native/march=rv64imfdv/g' ~/.config/pystencils/config.json
-    - sed -i s/g\+\+/clang++/g ~/.config/pystencils/config.json
+    - sed -i 's/march=native/march=rv64imfdvzicboz/g' ~/.config/pystencils/config.json
+    - sed -i s/g\+\+/clang++-15/g ~/.config/pystencils/config.json
     - sed -i 's/fopenmp/fopenmp=libgomp -I\/usr\/include\/riscv64-linux-gnu/g' ~/.config/pystencils/config.json
 
 minimal-conda:
diff --git a/pystencils/backends/riscv_instruction_sets.py b/pystencils/backends/riscv_instruction_sets.py
index 8e0ab7edd22b90312ff434da01aa4d489c36f1d1..3bfc957b695b2dd9dd45dfbff74b0fea52be8cc0 100644
--- a/pystencils/backends/riscv_instruction_sets.py
+++ b/pystencils/backends/riscv_instruction_sets.py
@@ -106,4 +106,7 @@ def get_vector_instruction_set_riscv(data_type='double', instruction_set='rvv'):
     result['any'] += ' > 0x0'
     result['all'] += f' == vsetvl_e{bits[data_type]}m1({vl})'
 
+    result['cachelineSize'] = 'cachelineSize()'
+    result['cachelineZero'] = 'cachelineZero((void*) {0})'
+
     return result
diff --git a/pystencils/include/riscv_v_helpers.h b/pystencils/include/riscv_v_helpers.h
new file mode 100644
index 0000000000000000000000000000000000000000..1969521ca273fa3f27ab86d164c6d3b3f070090d
--- /dev/null
+++ b/pystencils/include/riscv_v_helpers.h
@@ -0,0 +1,49 @@
+inline void cachelineZero(void * p) {
+#ifdef __riscv_zicboz
+	__asm__ volatile("cbo.zero (%0)"::"r"(p):"memory");
+#endif
+}
+
+inline size_t _cachelineSize() {
+	// allocate and fill with ones
+	const size_t max_size = 0x100000;
+	uint8_t data[2*max_size];
+	for (size_t i = 0; i < 2*max_size; ++i) {
+		data[i] = 0xff;
+	}
+	
+	// find alignment offset
+	size_t offset = max_size - ((uintptr_t) data) % max_size;
+
+	// zero a cacheline
+	cachelineZero((void*) (data + offset));
+
+	// make sure that at least one byte was zeroed
+	if (data[offset] != 0) {
+		return SIZE_MAX;
+	}
+
+	// make sure that nothing was zeroed before the pointer
+	if (data[offset-1] == 0) {
+		return SIZE_MAX;
+	}
+
+	// find the last byte that was zeroed
+	for (size_t size = 1; size < max_size; ++size) {
+		if (data[offset + size] != 0) {
+			return size;
+		}
+	}
+	
+	// too much was zeroed
+	return SIZE_MAX;
+}
+
+inline size_t cachelineSize() {
+#ifdef __riscv_zicboz
+	static size_t size = _cachelineSize();
+	return size;
+#else
+	return SIZE_MAX;
+#endif
+}
diff --git a/pystencils_tests/test_vectorization.py b/pystencils_tests/test_vectorization.py
index 3718770b9384e0f01dd899c3afed298208fc95a9..82a8495d2ff96eae38bed2ed4371f5d971df887f 100644
--- a/pystencils_tests/test_vectorization.py
+++ b/pystencils_tests/test_vectorization.py
@@ -60,7 +60,7 @@ def test_aligned_and_nt_stores(openmp, instruction_set=instruction_set):
     if instruction_set in ['sse'] or instruction_set.startswith('avx'):
         assert 'stream' in ast.instruction_set
         assert 'streamFence' in ast.instruction_set
-    if instruction_set in ['neon', 'vsx'] or instruction_set.startswith('sve'):
+    if instruction_set in ['neon', 'vsx', 'rvv'] or instruction_set.startswith('sve'):
         assert 'cachelineZero' in ast.instruction_set
     if instruction_set in ['vsx']:
         assert 'storeAAndFlushCacheline' in ast.instruction_set