Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

xz: add RISC-V BCJ filter

A later commit updates lib/decompress_unxz.c to enable this filter for
kernel decompression. lib/decompress_unxz.c is already used if
CONFIG_EFI_ZBOOT=y && CONFIG_KERNEL_XZ=y.

This filter can be used by Squashfs without modifications to the Squashfs
kernel code (only needs support in userspace Squashfs-tools).

Link: https://lkml.kernel.org/r/20240721133633.47721-13-lasse.collin@tukaani.org
Signed-off-by: Lasse Collin <lasse.collin@tukaani.org>
Reviewed-by: Sam James <sam@gentoo.org>
Cc: Albert Ou <aou@eecs.berkeley.edu>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Emil Renner Berthing <emil.renner.berthing@canonical.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Joel Stanley <joel@jms.id.au>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Jubin Zhong <zhongjubin@huawei.com>
Cc: Jules Maselbas <jmaselbas@zdiv.net>
Cc: Krzysztof Kozlowski <krzk@kernel.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Paul Walmsley <paul.walmsley@sifive.com>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Rui Li <me@lirui.org>
Cc: Simon Glass <sjg@chromium.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Lasse Collin and committed by
Andrew Morton
93d09773 4b62813f

+114 -3
+5
lib/xz/Kconfig
··· 40 40 default y 41 41 select XZ_DEC_BCJ 42 42 43 + config XZ_DEC_RISCV 44 + bool "RISC-V BCJ filter decoder" if EXPERT 45 + default y 46 + select XZ_DEC_BCJ 47 + 43 48 config XZ_DEC_MICROLZMA 44 49 bool "MicroLZMA decoder" 45 50 default n
+103 -1
lib/xz/xz_dec_bcj.c
··· 24 24 BCJ_ARM = 7, /* Little endian only */ 25 25 BCJ_ARMTHUMB = 8, /* Little endian only */ 26 26 BCJ_SPARC = 9, /* Big or little endian */ 27 - BCJ_ARM64 = 10 /* AArch64 */ 27 + BCJ_ARM64 = 10, /* AArch64 */ 28 + BCJ_RISCV = 11 /* RV32GQC_Zfh, RV64GQC_Zfh */ 28 29 } type; 29 30 30 31 /* ··· 389 388 } 390 389 #endif 391 390 391 + #ifdef XZ_DEC_RISCV 392 + static size_t bcj_riscv(struct xz_dec_bcj *s, uint8_t *buf, size_t size) 393 + { 394 + size_t i; 395 + uint32_t b1; 396 + uint32_t b2; 397 + uint32_t b3; 398 + uint32_t instr; 399 + uint32_t instr2; 400 + uint32_t instr2_rs1; 401 + uint32_t addr; 402 + 403 + if (size < 8) 404 + return 0; 405 + 406 + size -= 8; 407 + 408 + for (i = 0; i <= size; i += 2) { 409 + instr = buf[i]; 410 + 411 + if (instr == 0xEF) { 412 + /* JAL */ 413 + b1 = buf[i + 1]; 414 + if ((b1 & 0x0D) != 0) 415 + continue; 416 + 417 + b2 = buf[i + 2]; 418 + b3 = buf[i + 3]; 419 + 420 + addr = ((b1 & 0xF0) << 13) | (b2 << 9) | (b3 << 1); 421 + addr -= s->pos + (uint32_t)i; 422 + 423 + buf[i + 1] = (uint8_t)((b1 & 0x0F) 424 + | ((addr >> 8) & 0xF0)); 425 + 426 + buf[i + 2] = (uint8_t)(((addr >> 16) & 0x0F) 427 + | ((addr >> 7) & 0x10) 428 + | ((addr << 4) & 0xE0)); 429 + 430 + buf[i + 3] = (uint8_t)(((addr >> 4) & 0x7F) 431 + | ((addr >> 13) & 0x80)); 432 + 433 + i += 4 - 2; 434 + 435 + } else if ((instr & 0x7F) == 0x17) { 436 + /* AUIPC */ 437 + instr |= (uint32_t)buf[i + 1] << 8; 438 + instr |= (uint32_t)buf[i + 2] << 16; 439 + instr |= (uint32_t)buf[i + 3] << 24; 440 + 441 + if (instr & 0xE80) { 442 + /* AUIPC's rd doesn't equal x0 or x2. */ 443 + instr2 = get_unaligned_le32(buf + i + 4); 444 + 445 + if (((instr << 8) ^ (instr2 - 3)) & 0xF8003) { 446 + i += 6 - 2; 447 + continue; 448 + } 449 + 450 + addr = (instr & 0xFFFFF000) + (instr2 >> 20); 451 + 452 + instr = 0x17 | (2 << 7) | (instr2 << 12); 453 + instr2 = addr; 454 + } else { 455 + /* AUIPC's rd equals x0 or x2. */ 456 + instr2_rs1 = instr >> 27; 457 + 458 + if ((uint32_t)((instr - 0x3117) << 18) 459 + >= (instr2_rs1 & 0x1D)) { 460 + i += 4 - 2; 461 + continue; 462 + } 463 + 464 + addr = get_unaligned_be32(buf + i + 4); 465 + addr -= s->pos + (uint32_t)i; 466 + 467 + instr2 = (instr >> 12) | (addr << 20); 468 + 469 + instr = 0x17 | (instr2_rs1 << 7) 470 + | ((addr + 0x800) & 0xFFFFF000); 471 + } 472 + 473 + put_unaligned_le32(instr, buf + i); 474 + put_unaligned_le32(instr2, buf + i + 4); 475 + 476 + i += 8 - 2; 477 + } 478 + } 479 + 480 + return i; 481 + } 482 + #endif 483 + 392 484 /* 393 485 * Apply the selected BCJ filter. Update *pos and s->pos to match the amount 394 486 * of data that got filtered. ··· 532 438 #ifdef XZ_DEC_ARM64 533 439 case BCJ_ARM64: 534 440 filtered = bcj_arm64(s, buf, size); 441 + break; 442 + #endif 443 + #ifdef XZ_DEC_RISCV 444 + case BCJ_RISCV: 445 + filtered = bcj_riscv(s, buf, size); 535 446 break; 536 447 #endif 537 448 default: ··· 714 615 #endif 715 616 #ifdef XZ_DEC_ARM64 716 617 case BCJ_ARM64: 618 + #endif 619 + #ifdef XZ_DEC_RISCV 620 + case BCJ_RISCV: 717 621 #endif 718 622 break; 719 623
+1 -1
lib/xz/xz_dec_syms.c
··· 22 22 #endif 23 23 24 24 MODULE_DESCRIPTION("XZ decompressor"); 25 - MODULE_VERSION("1.1"); 25 + MODULE_VERSION("1.2"); 26 26 MODULE_AUTHOR("Lasse Collin <lasse.collin@tukaani.org> and Igor Pavlov"); 27 27 MODULE_LICENSE("Dual BSD/GPL");
+5 -1
lib/xz/xz_private.h
··· 39 39 # ifdef CONFIG_XZ_DEC_ARM64 40 40 # define XZ_DEC_ARM64 41 41 # endif 42 + # ifdef CONFIG_XZ_DEC_RISCV 43 + # define XZ_DEC_RISCV 44 + # endif 42 45 # ifdef CONFIG_XZ_DEC_MICROLZMA 43 46 # define XZ_DEC_MICROLZMA 44 47 # endif ··· 105 102 # if defined(XZ_DEC_X86) || defined(XZ_DEC_POWERPC) \ 106 103 || defined(XZ_DEC_IA64) \ 107 104 || defined(XZ_DEC_ARM) || defined(XZ_DEC_ARMTHUMB) \ 108 - || defined(XZ_DEC_SPARC) || defined(XZ_DEC_ARM64) 105 + || defined(XZ_DEC_SPARC) || defined(XZ_DEC_ARM64) \ 106 + || defined(XZ_DEC_RISCV) 109 107 # define XZ_DEC_BCJ 110 108 # endif 111 109 #endif