| ... | ... | @@ -447,6 +447,142 @@ inline fn getAArch64CpuFeature(comptime feat_reg: []const u8) u64 { |
| 447 | 447 | ); |
| 448 | 448 | } |
| 449 | 449 | |
| 450 | const riscv = struct { |
| 451 | const linux = std.os.linux; |
| 452 | const RISCV_HWPROBE = linux.RISCV_HWPROBE; |
| 453 | |
| 454 | fn setFeature(cpu: *Target.Cpu, feature: Target.riscv.Feature, enabled: bool) void { |
| 455 | const idx = @as(Target.Cpu.Feature.Set.Index, @backingInt(feature)); |
| 456 | |
| 457 | if (enabled) cpu.features.addFeature(idx) else cpu.features.removeFeature(idx); |
| 458 | } |
| 459 | |
| 460 | inline fn set(value: u64, mask: u64) bool { |
| 461 | return (value & mask) == mask; |
| 462 | } |
| 463 | |
| 464 | pub fn detectCpuFeatures(cpu: *Target.Cpu) void { |
| 465 | var probes = [_]linux.riscv_hwprobe{ |
| 466 | .{ .key = RISCV_HWPROBE.KEY.BASE_BEHAVIOR, .value = 0 }, |
| 467 | .{ .key = RISCV_HWPROBE.KEY.IMA_EXT_0, .value = 0 }, |
| 468 | .{ .key = RISCV_HWPROBE.KEY.MISALIGNED_SCALAR_PERF, .value = 0 }, |
| 469 | .{ .key = RISCV_HWPROBE.KEY.MISALIGNED_VECTOR_PERF, .value = 0 }, |
| 470 | .{ .key = RISCV_HWPROBE.KEY.VENDOR_EXT_MIPS_0, .value = 0 }, |
| 471 | .{ .key = RISCV_HWPROBE.KEY.VENDOR_EXT_SIFIVE_0, .value = 0 }, |
| 472 | .{ .key = RISCV_HWPROBE.KEY.IMA_EXT_1, .value = 0 }, |
| 473 | }; |
| 474 | |
| 475 | const rc = linux.sys_riscv_hwprobe(&probes, probes.len, 0, null, 0); |
| 476 | if (linux.errno(rc) == .NOSYS) |
| 477 | return; |
| 478 | |
| 479 | var ima_support = false; |
| 480 | for (probes) |probe| { |
| 481 | const value = probe.value; |
| 482 | |
| 483 | switch (probe.key) { |
| 484 | -1 => continue, // The running kernel doesn't know this key. |
| 485 | RISCV_HWPROBE.KEY.BASE_BEHAVIOR => { |
| 486 | ima_support = set(value, RISCV_HWPROBE.BASE_BEHAVIOR_IMA); |
| 487 | setFeature(cpu, Target.riscv.Feature.i, ima_support); |
| 488 | setFeature(cpu, Target.riscv.Feature.m, ima_support); |
| 489 | setFeature(cpu, Target.riscv.Feature.a, ima_support); |
| 490 | }, |
| 491 | RISCV_HWPROBE.KEY.IMA_EXT_0 => { |
| 492 | // https://bugzilla.kernel.org/show_bug.cgi?id=221874 |
| 493 | const fd_support = set(value, RISCV_HWPROBE.IMA_EXT_0.IMA_FD); |
| 494 | setFeature(cpu, .f, ima_support and fd_support); |
| 495 | setFeature(cpu, .d, ima_support and fd_support); |
| 496 | setFeature(cpu, .c, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.IMA_C)); |
| 497 | setFeature(cpu, .v, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.IMA_V)); |
| 498 | setFeature(cpu, .zba, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBA)); |
| 499 | setFeature(cpu, .zbb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBB)); |
| 500 | setFeature(cpu, .zbs, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBS)); |
| 501 | setFeature(cpu, .zicboz, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICBOZ)); |
| 502 | setFeature(cpu, .zbc, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBC)); |
| 503 | setFeature(cpu, .zbkb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBKB)); |
| 504 | setFeature(cpu, .zbkc, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBKC)); |
| 505 | setFeature(cpu, .zbkx, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBKX)); |
| 506 | setFeature(cpu, .zknd, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKND)); |
| 507 | setFeature(cpu, .zkne, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKNE)); |
| 508 | setFeature(cpu, .zknh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKNH)); |
| 509 | setFeature(cpu, .zksed, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKSED)); |
| 510 | setFeature(cpu, .zksh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKSH)); |
| 511 | setFeature(cpu, .zkt, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKT)); |
| 512 | setFeature(cpu, .zvbb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVBB)); |
| 513 | setFeature(cpu, .zvbc, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVBC)); |
| 514 | setFeature(cpu, .zvkb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKB)); |
| 515 | setFeature(cpu, .zvkg, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKG)); |
| 516 | setFeature(cpu, .zvkned, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKNED)); |
| 517 | setFeature(cpu, .zvknha, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKNHA)); |
| 518 | setFeature(cpu, .zvknhb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKNHB)); |
| 519 | setFeature(cpu, .zvksed, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKSED)); |
| 520 | setFeature(cpu, .zvksh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKSH)); |
| 521 | setFeature(cpu, .zvkt, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKT)); |
| 522 | setFeature(cpu, .zfh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZFH)); |
| 523 | setFeature(cpu, .zfhmin, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZFHMIN)); |
| 524 | setFeature(cpu, .zihintntl, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIHINTNTL)); |
| 525 | setFeature(cpu, .zvfh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVFH)); |
| 526 | setFeature(cpu, .zvfhmin, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVFHMIN)); |
| 527 | setFeature(cpu, .zfa, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZFA)); |
| 528 | setFeature(cpu, .ztso, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZTSO)); |
| 529 | setFeature(cpu, .zacas, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZACAS)); |
| 530 | setFeature(cpu, .zicntr, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICNTR)); |
| 531 | setFeature(cpu, .zicond, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICOND)); |
| 532 | setFeature(cpu, .zihintpause, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIHINTPAUSE)); |
| 533 | setFeature(cpu, .zihpm, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIHPM)); |
| 534 | setFeature(cpu, .zve32x, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE32X)); |
| 535 | setFeature(cpu, .zve32f, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE32F)); |
| 536 | setFeature(cpu, .zve64x, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE64X)); |
| 537 | setFeature(cpu, .zve64f, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE64F)); |
| 538 | setFeature(cpu, .zve64d, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE64D)); |
| 539 | setFeature(cpu, .zimop, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIMOP)); |
| 540 | setFeature(cpu, .zca, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCA)); |
| 541 | setFeature(cpu, .zcb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCB)); |
| 542 | setFeature(cpu, .zcd, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCD)); |
| 543 | setFeature(cpu, .zcf, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCF)); |
| 544 | setFeature(cpu, .zcmop, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCMOP)); |
| 545 | setFeature(cpu, .zawrs, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZAWRS)); |
| 546 | setFeature(cpu, .supm, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_SUPM)); |
| 547 | setFeature(cpu, .zicntr, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICNTR)); |
| 548 | setFeature(cpu, .zihpm, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIHPM)); |
| 549 | setFeature(cpu, .zfbfmin, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZFBFMIN)); |
| 550 | setFeature(cpu, .zvfbfmin, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVFBFMIN)); |
| 551 | setFeature(cpu, .zvfbfwma, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVFBFWMA)); |
| 552 | setFeature(cpu, .zicbom, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICBOM)); |
| 553 | setFeature(cpu, .zaamo, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZAAMO)); |
| 554 | setFeature(cpu, .zalrsc, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZALRSC)); |
| 555 | setFeature(cpu, .zabha, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZABHA)); |
| 556 | setFeature(cpu, .zalasr, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZALASR)); |
| 557 | setFeature(cpu, .zicbop, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICBOP)); |
| 558 | setFeature(cpu, .zilsd, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZILSD)); |
| 559 | setFeature(cpu, .zclsd, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCLSD)); |
| 560 | setFeature(cpu, .experimental_zicfilp, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICFILP)); |
| 561 | }, |
| 562 | RISCV_HWPROBE.KEY.MISALIGNED_SCALAR_PERF => { |
| 563 | setFeature(cpu, .unaligned_scalar_mem, value == RISCV_HWPROBE.MISALIGNED_SCALAR.FAST); |
| 564 | }, |
| 565 | RISCV_HWPROBE.KEY.MISALIGNED_VECTOR_PERF => { |
| 566 | setFeature(cpu, .unaligned_vector_mem, value == RISCV_HWPROBE.MISALIGNED_VECTOR.FAST); |
| 567 | }, |
| 568 | RISCV_HWPROBE.KEY.VENDOR_EXT_MIPS_0 => { |
| 569 | setFeature(cpu, .xmipsexectl, ima_support and set(value, RISCV_HWPROBE.MIPS_VENDOR_EXT_XMIPSEXECTL)); |
| 570 | }, |
| 571 | RISCV_HWPROBE.KEY.VENDOR_EXT_SIFIVE_0 => { |
| 572 | setFeature(cpu, .xsfvqmaccdod, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVQMACCDOD)); |
| 573 | setFeature(cpu, .xsfvqmaccqoq, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVQMACCQOQ)); |
| 574 | setFeature(cpu, .xsfvfnrclipxfqf, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVFNRCLIPXFQF)); |
| 575 | setFeature(cpu, .xsfvfwmaccqqq, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVFWMACCQQQ)); |
| 576 | }, |
| 577 | RISCV_HWPROBE.KEY.IMA_EXT_1 => { |
| 578 | setFeature(cpu, .experimental_zicfiss, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_1_EXT_ZICFISS)); |
| 579 | }, |
| 580 | else => unreachable, |
| 581 | } |
| 582 | } |
| 583 | } |
| 584 | }; |
| 585 | |
| 450 | 586 | pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu { |
| 451 | 587 | var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch |err| switch (err) { |
| 452 | 588 | else => return null, |
| ... | ... | @@ -457,11 +593,8 @@ pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu { |
| 457 | 593 | var file_reader = file.reader(io, &buffer); |
| 458 | 594 | |
| 459 | 595 | const current_arch = builtin.cpu.arch; |
| 460 | | switch (current_arch) { |
| 461 | | .arm, .armeb, .thumb, .thumbeb => { |
| 462 | | return ArmCpuinfoParser.parse(current_arch, &file_reader.interface) catch null; |
| 463 | | }, |
| 464 | | .aarch64, .aarch64_be => { |
| 596 | return switch (current_arch) { |
| 597 | .aarch64, .aarch64_be => b: { |
| 465 | 598 | const registers = [12]u64{ |
| 466 | 599 | getAArch64CpuFeature("MIDR_EL1"), |
| 467 | 600 | getAArch64CpuFeature("ID_AA64PFR0_EL1"), |
| ... | ... | @@ -477,23 +610,27 @@ pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu { |
| 477 | 610 | getAArch64CpuFeature("ID_AA64MMFR2_EL1"), |
| 478 | 611 | }; |
| 479 | 612 | |
| 480 | | const core = @import("arm.zig").aarch64.detectNativeCpuAndFeatures(current_arch, registers); |
| 481 | | return core; |
| 482 | | }, |
| 483 | | .sparc, .sparc64 => { |
| 484 | | return SparcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null; |
| 485 | | }, |
| 486 | | .powerpc, .powerpcle, .powerpc64, .powerpc64le => { |
| 487 | | return PowerpcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null; |
| 488 | | }, |
| 489 | | .riscv64, .riscv32 => { |
| 490 | | return RiscvCpuinfoParser.parse(current_arch, &file_reader.interface) catch null; |
| 491 | | }, |
| 492 | | .s390x => { |
| 493 | | return S390xCpuinfoParser.parse(current_arch, &file_reader.interface) catch null; |
| 613 | break :b @import("arm.zig").aarch64.detectNativeCpuAndFeatures(current_arch, registers); |
| 494 | 614 | }, |
| 495 | | else => {}, |
| 496 | | } |
| 615 | .arm, .armeb, .thumb, .thumbeb => ArmCpuinfoParser.parse(current_arch, &file_reader.interface) catch null, |
| 616 | .powerpc, .powerpcle, .powerpc64, .powerpc64le => PowerpcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null, |
| 617 | .riscv64, .riscv32 => b: { |
| 618 | var cpu = (RiscvCpuinfoParser.parse(current_arch, &file_reader.interface) catch null) orelse cpu: { |
| 619 | const model = Target.Cpu.Model.generic(current_arch); |
| 620 | break :cpu Target.Cpu{ |
| 621 | .arch = current_arch, |
| 622 | .model = model, |
| 623 | .features = model.features, |
| 624 | }; |
| 625 | }; |
| 626 | |
| 627 | riscv.detectCpuFeatures(&cpu); |
| 628 | cpu.features.populateDependencies(cpu.arch.allFeaturesList()); |
| 497 | 629 | |
| 498 | | return null; |
| 630 | break :b cpu; |
| 631 | }, |
| 632 | .s390x => S390xCpuinfoParser.parse(current_arch, &file_reader.interface) catch null, |
| 633 | .sparc, .sparc64 => SparcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null, |
| 634 | else => null, |
| 635 | }; |
| 499 | 636 | } |