diff options
author | 2023-02-21 18:24:12 -0800 | |
---|---|---|
committer | 2023-02-21 18:24:12 -0800 | |
commit | 5b7c4cabbb65f5c469464da6c5f614cbd7f730f2 (patch) | |
tree | cc5c2d0a898769fd59549594fedb3ee6f84e59a0 /tools/testing/selftests/powerpc/alignment | |
download | linux-5b7c4cabbb65f5c469464da6c5f614cbd7f730f2.tar.gz linux-5b7c4cabbb65f5c469464da6c5f614cbd7f730f2.zip |
Merge tag 'net-next-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-nextgrafted
Pull networking updates from Jakub Kicinski:
"Core:
- Add dedicated kmem_cache for typical/small skb->head, avoid having
to access struct page at kfree time, and improve memory use.
- Introduce sysctl to set default RPS configuration for new netdevs.
- Define Netlink protocol specification format which can be used to
describe messages used by each family and auto-generate parsers.
Add tools for generating kernel data structures and uAPI headers.
- Expose all net/core sysctls inside netns.
- Remove 4s sleep in netpoll if carrier is instantly detected on
boot.
- Add configurable limit of MDB entries per port, and port-vlan.
- Continue populating drop reasons throughout the stack.
- Retire a handful of legacy Qdiscs and classifiers.
Protocols:
- Support IPv4 big TCP (TSO frames larger than 64kB).
- Add IP_LOCAL_PORT_RANGE socket option, to control local port range
on socket by socket basis.
- Track and report in procfs number of MPTCP sockets used.
- Support mixing IPv4 and IPv6 flows in the in-kernel MPTCP path
manager.
- IPv6: don't check net.ipv6.route.max_size and rely on garbage
collection to free memory (similarly to IPv4).
- Support Penultimate Segment Pop (PSP) flavor in SRv6 (RFC8986).
- ICMP: add per-rate limit counters.
- Add support for user scanning requests in ieee802154.
- Remove static WEP support.
- Support minimal Wi-Fi 7 Extremely High Throughput (EHT) rate
reporting.
- WiFi 7 EHT channel puncturing support (client & AP).
BPF:
- Add a rbtree data structure following the "next-gen data structure"
precedent set by recently added linked list, that is, by using
kfunc + kptr instead of adding a new BPF map type.
- Expose XDP hints via kfuncs with initial support for RX hash and
timestamp metadata.
- Add BPF_F_NO_TUNNEL_KEY extension to bpf_skb_set_tunnel_key to
better support decap on GRE tunnel devices not operating in collect
metadata.
- Improve x86 JIT's codegen for PROBE_MEM runtime error checks.
- Remove the need for trace_printk_lock for bpf_trace_printk and
bpf_trace_vprintk helpers.
- Extend libbpf's bpf_tracing.h support for tracing arguments of
kprobes/uprobes and syscall as a special case.
- Significantly reduce the search time for module symbols by
livepatch and BPF.
- Enable cpumasks to be used as kptrs, which is useful for tracing
programs tracking which tasks end up running on which CPUs in
different time intervals.
- Add support for BPF trampoline on s390x and riscv64.
- Add capability to export the XDP features supported by the NIC.
- Add __bpf_kfunc tag for marking kernel functions as kfuncs.
- Add cgroup.memory=nobpf kernel parameter option to disable BPF
memory accounting for container environments.
Netfilter:
- Remove the CLUSTERIP target. It has been marked as obsolete for
years, and we still have WARN splats wrt races of the out-of-band
/proc interface installed by this target.
- Add 'destroy' commands to nf_tables. They are identical to the
existing 'delete' commands, but do not return an error if the
referenced object (set, chain, rule...) did not exist.
Driver API:
- Improve cpumask_local_spread() locality to help NICs set the right
IRQ affinity on AMD platforms.
- Separate C22 and C45 MDIO bus transactions more clearly.
- Introduce new DCB table to control DSCP rewrite on egress.
- Support configuration of Physical Layer Collision Avoidance (PLCA)
Reconciliation Sublayer (RS) (802.3cg-2019). Modern version of
shared medium Ethernet.
- Support for MAC Merge layer (IEEE 802.3-2018 clause 99). Allowing
preemption of low priority frames by high priority frames.
- Add support for controlling MACSec offload using netlink SET.
- Rework devlink instance refcounts to allow registration and
de-registration under the instance lock. Split the code into
multiple files, drop some of the unnecessarily granular locks and
factor out common parts of netlink operation handling.
- Add TX frame aggregation parameters (for USB drivers).
- Add a new attr TCA_EXT_WARN_MSG to report TC (offload) warning
messages with notifications for debug.
- Allow offloading of UDP NEW connections via act_ct.
- Add support for per action HW stats in TC.
- Support hardware miss to TC action (continue processing in SW from
a specific point in the action chain).
- Warn if old Wireless Extension user space interface is used with
modern cfg80211/mac80211 drivers. Do not support Wireless
Extensions for Wi-Fi 7 devices at all. Everyone should switch to
using nl80211 interface instead.
- Improve the CAN bit timing configuration. Use extack to return
error messages directly to user space, update the SJW handling,
including the definition of a new default value that will benefit
CAN-FD controllers, by increasing their oscillator tolerance.
New hardware / drivers:
- Ethernet:
- nVidia BlueField-3 support (control traffic driver)
- Ethernet support for imx93 SoCs
- Motorcomm yt8531 gigabit Ethernet PHY
- onsemi NCN26000 10BASE-T1S PHY (with support for PLCA)
- Microchip LAN8841 PHY (incl. cable diagnostics and PTP)
- Amlogic gxl MDIO mux
- WiFi:
- RealTek RTL8188EU (rtl8xxxu)
- Qualcomm Wi-Fi 7 devices (ath12k)
- CAN:
- Renesas R-Car V4H
Drivers:
- Bluetooth:
- Set Per Platform Antenna Gain (PPAG) for Intel controllers.
- Ethernet NICs:
- Intel (1G, igc):
- support TSN / Qbv / packet scheduling features of i226 model
- Intel (100G, ice):
- use GNSS subsystem instead of TTY
- multi-buffer XDP support
- extend support for GPIO pins to E823 devices
- nVidia/Mellanox:
- update the shared buffer configuration on PFC commands
- implement PTP adjphase function for HW offset control
- TC support for Geneve and GRE with VF tunnel offload
- more efficient crypto key management method
- multi-port eswitch support
- Netronome/Corigine:
- add DCB IEEE support
- support IPsec offloading for NFP3800
- Freescale/NXP (enetc):
- support XDP_REDIRECT for XDP non-linear buffers
- improve reconfig, avoid link flap and waiting for idle
- support MAC Merge layer
- Other NICs:
- sfc/ef100: add basic devlink support for ef100
- ionic: rx_push mode operation (writing descriptors via MMIO)
- bnxt: use the auxiliary bus abstraction for RDMA
- r8169: disable ASPM and reset bus in case of tx timeout
- cpsw: support QSGMII mode for J721e CPSW9G
- cpts: support pulse-per-second output
- ngbe: add an mdio bus driver
- usbnet: optimize usbnet_bh() by avoiding unnecessary queuing
- r8152: handle devices with FW with NCM support
- amd-xgbe: support 10Mbps, 2.5GbE speeds and rx-adaptation
- virtio-net: support multi buffer XDP
- virtio/vsock: replace virtio_vsock_pkt with sk_buff
- tsnep: XDP support
- Ethernet high-speed switches:
- nVidia/Mellanox (mlxsw):
- add support for latency TLV (in FW control messages)
- Microchip (sparx5):
- separate explicit and implicit traffic forwarding rules, make
the implicit rules always active
- add support for egress DSCP rewrite
- IS0 VCAP support (Ingress Classification)
- IS2 VCAP filters (protos, L3 addrs, L4 ports, flags, ToS
etc.)
- ES2 VCAP support (Egress Access Control)
- support for Per-Stream Filtering and Policing (802.1Q,
8.6.5.1)
- Ethernet embedded switches:
- Marvell (mv88e6xxx):
- add MAB (port auth) offload support
- enable PTP receive for mv88e6390
- NXP (ocelot):
- support MAC Merge layer
- support for the the vsc7512 internal copper phys
- Microchip:
- lan9303: convert to PHYLINK
- lan966x: support TC flower filter statistics
- lan937x: PTP support for KSZ9563/KSZ8563 and LAN937x
- lan937x: support Credit Based Shaper configuration
- ksz9477: support Energy Efficient Ethernet
- other:
- qca8k: convert to regmap read/write API, use bulk operations
- rswitch: Improve TX timestamp accuracy
- Intel WiFi (iwlwifi):
- EHT (Wi-Fi 7) rate reporting
- STEP equalizer support: transfer some STEP (connection to radio
on platforms with integrated wifi) related parameters from the
BIOS to the firmware.
- Qualcomm 802.11ax WiFi (ath11k):
- IPQ5018 support
- Fine Timing Measurement (FTM) responder role support
- channel 177 support
- MediaTek WiFi (mt76):
- per-PHY LED support
- mt7996: EHT (Wi-Fi 7) support
- Wireless Ethernet Dispatch (WED) reset support
- switch to using page pool allocator
- RealTek WiFi (rtw89):
- support new version of Bluetooth co-existance
- Mobile:
- rmnet: support TX aggregation"
* tag 'net-next-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1872 commits)
page_pool: add a comment explaining the fragment counter usage
net: ethtool: fix __ethtool_dev_mm_supported() implementation
ethtool: pse-pd: Fix double word in comments
xsk: add linux/vmalloc.h to xsk.c
sefltests: netdevsim: wait for devlink instance after netns removal
selftest: fib_tests: Always cleanup before exit
net/mlx5e: Align IPsec ASO result memory to be as required by hardware
net/mlx5e: TC, Set CT miss to the specific ct action instance
net/mlx5e: Rename CHAIN_TO_REG to MAPPED_OBJ_TO_REG
net/mlx5: Refactor tc miss handling to a single function
net/mlx5: Kconfig: Make tc offload depend on tc skb extension
net/sched: flower: Support hardware miss to tc action
net/sched: flower: Move filter handle initialization earlier
net/sched: cls_api: Support hardware miss to tc action
net/sched: Rename user cookie and act cookie
sfc: fix builds without CONFIG_RTC_LIB
sfc: clean up some inconsistent indentings
net/mlx4_en: Introduce flexible array to silence overflow warning
net: lan966x: Fix possible deadlock inside PTP
net/ulp: Remove redundant ->clone() test in inet_clone_ulp().
...
Diffstat (limited to 'tools/testing/selftests/powerpc/alignment')
4 files changed, 757 insertions, 0 deletions
diff --git a/tools/testing/selftests/powerpc/alignment/.gitignore b/tools/testing/selftests/powerpc/alignment/.gitignore new file mode 100644 index 000000000..28bc6ca13 --- /dev/null +++ b/tools/testing/selftests/powerpc/alignment/.gitignore @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only +copy_first_unaligned +alignment_handler diff --git a/tools/testing/selftests/powerpc/alignment/Makefile b/tools/testing/selftests/powerpc/alignment/Makefile new file mode 100644 index 000000000..93e9af374 --- /dev/null +++ b/tools/testing/selftests/powerpc/alignment/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-only +TEST_GEN_PROGS := copy_first_unaligned alignment_handler + +top_srcdir = ../../../../.. +include ../../lib.mk + +$(TEST_GEN_PROGS): ../harness.c ../utils.c diff --git a/tools/testing/selftests/powerpc/alignment/alignment_handler.c b/tools/testing/selftests/powerpc/alignment/alignment_handler.c new file mode 100644 index 000000000..33ee34fc0 --- /dev/null +++ b/tools/testing/selftests/powerpc/alignment/alignment_handler.c @@ -0,0 +1,680 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Test the powerpc alignment handler on POWER8/POWER9 + * + * Copyright (C) 2017 IBM Corporation (Michael Neuling, Andrew Donnellan) + */ + +/* + * This selftest exercises the powerpc alignment fault handler. + * + * We create two sets of source and destination buffers, one in regular memory, + * the other cache-inhibited (by default we use /dev/fb0 for this, but an + * alterative path for cache-inhibited memory may be provided, e.g. memtrace). + * + * We initialise the source buffers, then use whichever set of load/store + * instructions is under test to copy bytes from the source buffers to the + * destination buffers. For the regular buffers, these instructions will + * execute normally. For the cache-inhibited buffers, these instructions + * will trap and cause an alignment fault, and the alignment fault handler + * will emulate the particular instruction under test. We then compare the + * destination buffers to ensure that the native and emulated cases give the + * same result. + * + * TODO: + * - Any FIXMEs below + * - Test VSX regs < 32 and > 32 + * - Test all loads and stores + * - Check update forms do update register + * - Test alignment faults over page boundary + * + * Some old binutils may not support all the instructions. + */ + + +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <getopt.h> +#include <setjmp.h> +#include <signal.h> + +#include "utils.h" +#include "instructions.h" + +int bufsize; +int debug; +int testing; +volatile int gotsig; +bool prefixes_enabled; +char *cipath = "/dev/fb0"; +long cioffset; + +void sighandler(int sig, siginfo_t *info, void *ctx) +{ + ucontext_t *ucp = ctx; + + if (!testing) { + signal(sig, SIG_DFL); + kill(0, sig); + } + gotsig = sig; +#ifdef __powerpc64__ + if (prefixes_enabled) { + u32 inst = *(u32 *)ucp->uc_mcontext.gp_regs[PT_NIP]; + ucp->uc_mcontext.gp_regs[PT_NIP] += ((inst >> 26 == 1) ? 8 : 4); + } else { + ucp->uc_mcontext.gp_regs[PT_NIP] += 4; + } +#else + ucp->uc_mcontext.uc_regs->gregs[PT_NIP] += 4; +#endif +} + +#define XFORM(reg, n) " " #reg " ,%"#n",%2 ;" +#define DFORM(reg, n) " " #reg " ,0(%"#n") ;" + +#define TEST(name, ld_op, st_op, form, ld_reg, st_reg) \ + void test_##name(char *s, char *d) \ + { \ + asm volatile( \ + #ld_op form(ld_reg, 0) \ + #st_op form(st_reg, 1) \ + :: "r"(s), "r"(d), "r"(0) \ + : "memory", "vs0", "vs32", "r31"); \ + } \ + rc |= do_test(#name, test_##name) + +#define TESTP(name, ld_op, st_op, ld_reg, st_reg) \ + void test_##name(char *s, char *d) \ + { \ + asm volatile( \ + ld_op(ld_reg, %0, 0, 0) \ + st_op(st_reg, %1, 0, 0) \ + :: "r"(s), "r"(d), "r"(0) \ + : "memory", "vs0", "vs32", "r31"); \ + } \ + rc |= do_test(#name, test_##name) + +#define LOAD_VSX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 32, 32) +#define STORE_VSX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 32) +#define LOAD_VSX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 32, 32) +#define STORE_VSX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 32) +#define LOAD_VMX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 0, 32) +#define STORE_VMX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 0) +#define LOAD_VMX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 0, 32) +#define STORE_VMX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 0) + +#define LOAD_XFORM_TEST(op) TEST(op, op, stdx, XFORM, 31, 31) +#define STORE_XFORM_TEST(op) TEST(op, ldx, op, XFORM, 31, 31) +#define LOAD_DFORM_TEST(op) TEST(op, op, std, DFORM, 31, 31) +#define STORE_DFORM_TEST(op) TEST(op, ld, op, DFORM, 31, 31) + +#define LOAD_FLOAT_DFORM_TEST(op) TEST(op, op, stfd, DFORM, 0, 0) +#define STORE_FLOAT_DFORM_TEST(op) TEST(op, lfd, op, DFORM, 0, 0) +#define LOAD_FLOAT_XFORM_TEST(op) TEST(op, op, stfdx, XFORM, 0, 0) +#define STORE_FLOAT_XFORM_TEST(op) TEST(op, lfdx, op, XFORM, 0, 0) + +#define LOAD_MLS_PREFIX_TEST(op) TESTP(op, op, PSTD, 31, 31) +#define STORE_MLS_PREFIX_TEST(op) TESTP(op, PLD, op, 31, 31) + +#define LOAD_8LS_PREFIX_TEST(op) TESTP(op, op, PSTD, 31, 31) +#define STORE_8LS_PREFIX_TEST(op) TESTP(op, PLD, op, 31, 31) + +#define LOAD_FLOAT_MLS_PREFIX_TEST(op) TESTP(op, op, PSTFD, 0, 0) +#define STORE_FLOAT_MLS_PREFIX_TEST(op) TESTP(op, PLFD, op, 0, 0) + +#define LOAD_VSX_8LS_PREFIX_TEST(op, tail) TESTP(op, op, PSTXV ## tail, 0, 32) +#define STORE_VSX_8LS_PREFIX_TEST(op, tail) TESTP(op, PLXV ## tail, op, 32, 0) + +/* FIXME: Unimplemented tests: */ +// STORE_DFORM_TEST(stq) /* FIXME: need two registers for quad */ +// STORE_DFORM_TEST(stswi) /* FIXME: string instruction */ + +// STORE_XFORM_TEST(stwat) /* AMO can't emulate or run on CI */ +// STORE_XFORM_TEST(stdat) /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */ + + +/* preload byte by byte */ +void preload_data(void *dst, int offset, int width) +{ + char *c = dst; + int i; + + c += offset; + + for (i = 0 ; i < width ; i++) + c[i] = i; +} + +int test_memcpy(void *dst, void *src, int size, int offset, + void (*test_func)(char *, char *)) +{ + char *s, *d; + + s = src; + s += offset; + d = dst; + d += offset; + + assert(size == 16); + gotsig = 0; + testing = 1; + + test_func(s, d); /* run the actual test */ + + testing = 0; + if (gotsig) { + if (debug) + printf(" Got signal %i\n", gotsig); + return 1; + } + return 0; +} + +void dumpdata(char *s1, char *s2, int n, char *test_name) +{ + int i; + + printf(" %s: unexpected result:\n", test_name); + printf(" mem:"); + for (i = 0; i < n; i++) + printf(" %02x", s1[i]); + printf("\n"); + printf(" ci: "); + for (i = 0; i < n; i++) + printf(" %02x", s2[i]); + printf("\n"); +} + +int test_memcmp(void *s1, void *s2, int n, int offset, char *test_name) +{ + char *s1c, *s2c; + + s1c = s1; + s1c += offset; + s2c = s2; + s2c += offset; + + if (memcmp(s1c, s2c, n)) { + if (debug) { + printf("\n Compare failed. Offset:%i length:%i\n", + offset, n); + dumpdata(s1c, s2c, n, test_name); + } + return 1; + } + return 0; +} + +/* + * Do two memcpy tests using the same instructions. One cachable + * memory and the other doesn't. + */ +int do_test(char *test_name, void (*test_func)(char *, char *)) +{ + int offset, width, fd, rc, r; + void *mem0, *mem1, *ci0, *ci1; + + printf("\tDoing %s:\t", test_name); + + fd = open(cipath, O_RDWR); + if (fd < 0) { + printf("\n"); + perror("Can't open ci file now?"); + return 1; + } + + ci0 = mmap(NULL, bufsize, PROT_WRITE | PROT_READ, MAP_SHARED, + fd, cioffset); + ci1 = mmap(NULL, bufsize, PROT_WRITE | PROT_READ, MAP_SHARED, + fd, cioffset + bufsize); + + if ((ci0 == MAP_FAILED) || (ci1 == MAP_FAILED)) { + printf("\n"); + perror("mmap failed"); + SKIP_IF(1); + } + + rc = posix_memalign(&mem0, bufsize, bufsize); + if (rc) { + printf("\n"); + return rc; + } + + rc = posix_memalign(&mem1, bufsize, bufsize); + if (rc) { + printf("\n"); + free(mem0); + return rc; + } + + rc = 0; + /* + * offset = 0 is aligned but tests the workaround for the P9N + * DD2.1 vector CI load issue (see 5080332c2c89 "powerpc/64s: + * Add workaround for P9 vector CI load issue") + */ + for (offset = 0; offset < 16; offset++) { + width = 16; /* vsx == 16 bytes */ + r = 0; + + /* load pattern into memory byte by byte */ + preload_data(ci0, offset, width); + preload_data(mem0, offset, width); // FIXME: remove?? + memcpy(ci0, mem0, bufsize); + memcpy(ci1, mem1, bufsize); /* initialise output to the same */ + + /* sanity check */ + test_memcmp(mem0, ci0, width, offset, test_name); + + r |= test_memcpy(ci1, ci0, width, offset, test_func); + r |= test_memcpy(mem1, mem0, width, offset, test_func); + if (r && !debug) { + printf("FAILED: Got signal"); + rc = 1; + break; + } + + r |= test_memcmp(mem1, ci1, width, offset, test_name); + if (r && !debug) { + printf("FAILED: Wrong Data"); + rc = 1; + break; + } + } + + if (rc == 0) + printf("PASSED"); + + printf("\n"); + + munmap(ci0, bufsize); + munmap(ci1, bufsize); + free(mem0); + free(mem1); + close(fd); + + return rc; +} + +static bool can_open_cifile(void) +{ + int fd; + + fd = open(cipath, O_RDWR); + if (fd < 0) + return false; + + close(fd); + return true; +} + +int test_alignment_handler_vsx_206(void) +{ + int rc = 0; + + SKIP_IF(!can_open_cifile()); + SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06)); + + printf("VSX: 2.06B\n"); + LOAD_VSX_XFORM_TEST(lxvd2x); + LOAD_VSX_XFORM_TEST(lxvw4x); + LOAD_VSX_XFORM_TEST(lxsdx); + LOAD_VSX_XFORM_TEST(lxvdsx); + STORE_VSX_XFORM_TEST(stxvd2x); + STORE_VSX_XFORM_TEST(stxvw4x); + STORE_VSX_XFORM_TEST(stxsdx); + return rc; +} + +int test_alignment_handler_vsx_207(void) +{ + int rc = 0; + + SKIP_IF(!can_open_cifile()); + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_2_07)); + + printf("VSX: 2.07B\n"); + LOAD_VSX_XFORM_TEST(lxsspx); + LOAD_VSX_XFORM_TEST(lxsiwax); + LOAD_VSX_XFORM_TEST(lxsiwzx); + STORE_VSX_XFORM_TEST(stxsspx); + STORE_VSX_XFORM_TEST(stxsiwx); + return rc; +} + +int test_alignment_handler_vsx_300(void) +{ + int rc = 0; + + SKIP_IF(!can_open_cifile()); + + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00)); + printf("VSX: 3.00B\n"); + LOAD_VMX_DFORM_TEST(lxsd); + LOAD_VSX_XFORM_TEST(lxsibzx); + LOAD_VSX_XFORM_TEST(lxsihzx); + LOAD_VMX_DFORM_TEST(lxssp); + LOAD_VSX_DFORM_TEST(lxv); + LOAD_VSX_XFORM_TEST(lxvb16x); + LOAD_VSX_XFORM_TEST(lxvh8x); + LOAD_VSX_XFORM_TEST(lxvx); + LOAD_VSX_XFORM_TEST(lxvwsx); + LOAD_VSX_XFORM_TEST(lxvl); + LOAD_VSX_XFORM_TEST(lxvll); + STORE_VMX_DFORM_TEST(stxsd); + STORE_VSX_XFORM_TEST(stxsibx); + STORE_VSX_XFORM_TEST(stxsihx); + STORE_VMX_DFORM_TEST(stxssp); + STORE_VSX_DFORM_TEST(stxv); + STORE_VSX_XFORM_TEST(stxvb16x); + STORE_VSX_XFORM_TEST(stxvh8x); + STORE_VSX_XFORM_TEST(stxvx); + STORE_VSX_XFORM_TEST(stxvl); + STORE_VSX_XFORM_TEST(stxvll); + return rc; +} + +int test_alignment_handler_vsx_prefix(void) +{ + int rc = 0; + + SKIP_IF(!can_open_cifile()); + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1)); + + printf("VSX: PREFIX\n"); + LOAD_VSX_8LS_PREFIX_TEST(PLXSD, 0); + LOAD_VSX_8LS_PREFIX_TEST(PLXSSP, 0); + LOAD_VSX_8LS_PREFIX_TEST(PLXV0, 0); + LOAD_VSX_8LS_PREFIX_TEST(PLXV1, 1); + STORE_VSX_8LS_PREFIX_TEST(PSTXSD, 0); + STORE_VSX_8LS_PREFIX_TEST(PSTXSSP, 0); + STORE_VSX_8LS_PREFIX_TEST(PSTXV0, 0); + STORE_VSX_8LS_PREFIX_TEST(PSTXV1, 1); + return rc; +} + +int test_alignment_handler_integer(void) +{ + int rc = 0; + + SKIP_IF(!can_open_cifile()); + + printf("Integer\n"); + LOAD_DFORM_TEST(lbz); + LOAD_DFORM_TEST(lbzu); + LOAD_XFORM_TEST(lbzx); + LOAD_XFORM_TEST(lbzux); + LOAD_DFORM_TEST(lhz); + LOAD_DFORM_TEST(lhzu); + LOAD_XFORM_TEST(lhzx); + LOAD_XFORM_TEST(lhzux); + LOAD_DFORM_TEST(lha); + LOAD_DFORM_TEST(lhau); + LOAD_XFORM_TEST(lhax); + LOAD_XFORM_TEST(lhaux); + LOAD_XFORM_TEST(lhbrx); + LOAD_DFORM_TEST(lwz); + LOAD_DFORM_TEST(lwzu); + LOAD_XFORM_TEST(lwzx); + LOAD_XFORM_TEST(lwzux); + LOAD_DFORM_TEST(lwa); + LOAD_XFORM_TEST(lwax); + LOAD_XFORM_TEST(lwaux); + LOAD_XFORM_TEST(lwbrx); + LOAD_DFORM_TEST(ld); + LOAD_DFORM_TEST(ldu); + LOAD_XFORM_TEST(ldx); + LOAD_XFORM_TEST(ldux); + STORE_DFORM_TEST(stb); + STORE_XFORM_TEST(stbx); + STORE_DFORM_TEST(stbu); + STORE_XFORM_TEST(stbux); + STORE_DFORM_TEST(sth); + STORE_XFORM_TEST(sthx); + STORE_DFORM_TEST(sthu); + STORE_XFORM_TEST(sthux); + STORE_XFORM_TEST(sthbrx); + STORE_DFORM_TEST(stw); + STORE_XFORM_TEST(stwx); + STORE_DFORM_TEST(stwu); + STORE_XFORM_TEST(stwux); + STORE_XFORM_TEST(stwbrx); + STORE_DFORM_TEST(std); + STORE_XFORM_TEST(stdx); + STORE_DFORM_TEST(stdu); + STORE_XFORM_TEST(stdux); + +#ifdef __BIG_ENDIAN__ + LOAD_DFORM_TEST(lmw); + STORE_DFORM_TEST(stmw); +#endif + + return rc; +} + +int test_alignment_handler_integer_206(void) +{ + int rc = 0; + + SKIP_IF(!can_open_cifile()); + SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06)); + + printf("Integer: 2.06\n"); + + LOAD_XFORM_TEST(ldbrx); + STORE_XFORM_TEST(stdbrx); + + return rc; +} + +int test_alignment_handler_integer_prefix(void) +{ + int rc = 0; + + SKIP_IF(!can_open_cifile()); + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1)); + + printf("Integer: PREFIX\n"); + LOAD_MLS_PREFIX_TEST(PLBZ); + LOAD_MLS_PREFIX_TEST(PLHZ); + LOAD_MLS_PREFIX_TEST(PLHA); + LOAD_MLS_PREFIX_TEST(PLWZ); + LOAD_8LS_PREFIX_TEST(PLWA); + LOAD_8LS_PREFIX_TEST(PLD); + STORE_MLS_PREFIX_TEST(PSTB); + STORE_MLS_PREFIX_TEST(PSTH); + STORE_MLS_PREFIX_TEST(PSTW); + STORE_8LS_PREFIX_TEST(PSTD); + return rc; +} + +int test_alignment_handler_vmx(void) +{ + int rc = 0; + + SKIP_IF(!can_open_cifile()); + SKIP_IF(!have_hwcap(PPC_FEATURE_HAS_ALTIVEC)); + + printf("VMX\n"); + LOAD_VMX_XFORM_TEST(lvx); + + /* + * FIXME: These loads only load part of the register, so our + * testing method doesn't work. Also they don't take alignment + * faults, so it's kinda pointless anyway + * + LOAD_VMX_XFORM_TEST(lvebx) + LOAD_VMX_XFORM_TEST(lvehx) + LOAD_VMX_XFORM_TEST(lvewx) + LOAD_VMX_XFORM_TEST(lvxl) + */ + STORE_VMX_XFORM_TEST(stvx); + STORE_VMX_XFORM_TEST(stvebx); + STORE_VMX_XFORM_TEST(stvehx); + STORE_VMX_XFORM_TEST(stvewx); + STORE_VMX_XFORM_TEST(stvxl); + return rc; +} + +int test_alignment_handler_fp(void) +{ + int rc = 0; + + SKIP_IF(!can_open_cifile()); + + printf("Floating point\n"); + LOAD_FLOAT_DFORM_TEST(lfd); + LOAD_FLOAT_XFORM_TEST(lfdx); + LOAD_FLOAT_DFORM_TEST(lfdu); + LOAD_FLOAT_XFORM_TEST(lfdux); + LOAD_FLOAT_DFORM_TEST(lfs); + LOAD_FLOAT_XFORM_TEST(lfsx); + LOAD_FLOAT_DFORM_TEST(lfsu); + LOAD_FLOAT_XFORM_TEST(lfsux); + STORE_FLOAT_DFORM_TEST(stfd); + STORE_FLOAT_XFORM_TEST(stfdx); + STORE_FLOAT_DFORM_TEST(stfdu); + STORE_FLOAT_XFORM_TEST(stfdux); + STORE_FLOAT_DFORM_TEST(stfs); + STORE_FLOAT_XFORM_TEST(stfsx); + STORE_FLOAT_DFORM_TEST(stfsu); + STORE_FLOAT_XFORM_TEST(stfsux); + STORE_FLOAT_XFORM_TEST(stfiwx); + + return rc; +} + +int test_alignment_handler_fp_205(void) +{ + int rc = 0; + + SKIP_IF(!can_open_cifile()); + SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_05)); + + printf("Floating point: 2.05\n"); + + LOAD_FLOAT_DFORM_TEST(lfdp); + LOAD_FLOAT_XFORM_TEST(lfdpx); + LOAD_FLOAT_XFORM_TEST(lfiwax); + STORE_FLOAT_DFORM_TEST(stfdp); + STORE_FLOAT_XFORM_TEST(stfdpx); + + return rc; +} + +int test_alignment_handler_fp_206(void) +{ + int rc = 0; + + SKIP_IF(!can_open_cifile()); + SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06)); + + printf("Floating point: 2.06\n"); + + LOAD_FLOAT_XFORM_TEST(lfiwzx); + + return rc; +} + + +int test_alignment_handler_fp_prefix(void) +{ + int rc = 0; + + SKIP_IF(!can_open_cifile()); + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1)); + + printf("Floating point: PREFIX\n"); + LOAD_FLOAT_DFORM_TEST(lfs); + LOAD_FLOAT_MLS_PREFIX_TEST(PLFS); + LOAD_FLOAT_MLS_PREFIX_TEST(PLFD); + STORE_FLOAT_MLS_PREFIX_TEST(PSTFS); + STORE_FLOAT_MLS_PREFIX_TEST(PSTFD); + return rc; +} + +void usage(char *prog) +{ + printf("Usage: %s [options] [path [offset]]\n", prog); + printf(" -d Enable debug error output\n"); + printf("\n"); + printf("This test requires a POWER8, POWER9 or POWER10 CPU "); + printf("and either a usable framebuffer at /dev/fb0 or "); + printf("the path to usable cache inhibited memory and optional "); + printf("offset to be provided\n"); +} + +int main(int argc, char *argv[]) +{ + + struct sigaction sa; + int rc = 0; + int option = 0; + + while ((option = getopt(argc, argv, "d")) != -1) { + switch (option) { + case 'd': + debug++; + break; + default: + usage(argv[0]); + exit(1); + } + } + argc -= optind; + argv += optind; + + if (argc > 0) + cipath = argv[0]; + if (argc > 1) + cioffset = strtol(argv[1], 0, 0x10); + + bufsize = getpagesize(); + + sa.sa_sigaction = sighandler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO; + if (sigaction(SIGSEGV, &sa, NULL) == -1 + || sigaction(SIGBUS, &sa, NULL) == -1 + || sigaction(SIGILL, &sa, NULL) == -1) { + perror("sigaction"); + exit(1); + } + + prefixes_enabled = have_hwcap2(PPC_FEATURE2_ARCH_3_1); + + rc |= test_harness(test_alignment_handler_vsx_206, + "test_alignment_handler_vsx_206"); + rc |= test_harness(test_alignment_handler_vsx_207, + "test_alignment_handler_vsx_207"); + rc |= test_harness(test_alignment_handler_vsx_300, + "test_alignment_handler_vsx_300"); + rc |= test_harness(test_alignment_handler_vsx_prefix, + "test_alignment_handler_vsx_prefix"); + rc |= test_harness(test_alignment_handler_integer, + "test_alignment_handler_integer"); + rc |= test_harness(test_alignment_handler_integer_206, + "test_alignment_handler_integer_206"); + rc |= test_harness(test_alignment_handler_integer_prefix, + "test_alignment_handler_integer_prefix"); + rc |= test_harness(test_alignment_handler_vmx, + "test_alignment_handler_vmx"); + rc |= test_harness(test_alignment_handler_fp, + "test_alignment_handler_fp"); + rc |= test_harness(test_alignment_handler_fp_205, + "test_alignment_handler_fp_205"); + rc |= test_harness(test_alignment_handler_fp_206, + "test_alignment_handler_fp_206"); + rc |= test_harness(test_alignment_handler_fp_prefix, + "test_alignment_handler_fp_prefix"); + return rc; +} diff --git a/tools/testing/selftests/powerpc/alignment/copy_first_unaligned.c b/tools/testing/selftests/powerpc/alignment/copy_first_unaligned.c new file mode 100644 index 000000000..db4e8c680 --- /dev/null +++ b/tools/testing/selftests/powerpc/alignment/copy_first_unaligned.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2016, Chris Smart, IBM Corporation. + * + * Calls to copy_first which are not 128-byte aligned should be + * caught and sent a SIGBUS. + */ + +#include <signal.h> +#include <string.h> +#include <unistd.h> +#include "utils.h" +#include "instructions.h" + +unsigned int expected_instruction = PPC_INST_COPY_FIRST; +unsigned int instruction_mask = 0xfc2007fe; + +void signal_action_handler(int signal_num, siginfo_t *info, void *ptr) +{ + ucontext_t *ctx = ptr; +#ifdef __powerpc64__ + unsigned int *pc = (unsigned int *)ctx->uc_mcontext.gp_regs[PT_NIP]; +#else + unsigned int *pc = (unsigned int *)ctx->uc_mcontext.uc_regs->gregs[PT_NIP]; +#endif + + /* + * Check that the signal was on the correct instruction, using a + * mask because the compiler assigns the register at RB. + */ + if ((*pc & instruction_mask) == expected_instruction) + _exit(0); /* We hit the right instruction */ + + _exit(1); +} + +void setup_signal_handler(void) +{ + struct sigaction signal_action; + + memset(&signal_action, 0, sizeof(signal_action)); + signal_action.sa_sigaction = signal_action_handler; + signal_action.sa_flags = SA_SIGINFO; + sigaction(SIGBUS, &signal_action, NULL); +} + +char cacheline_buf[128] __cacheline_aligned; + +int test_copy_first_unaligned(void) +{ + /* Only run this test on a P9 or later */ + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00)); + + /* Register our signal handler with SIGBUS */ + setup_signal_handler(); + + /* +1 makes buf unaligned */ + copy_first(cacheline_buf+1); + + /* We should not get here */ + return 1; +} + +int main(int argc, char *argv[]) +{ + return test_harness(test_copy_first_unaligned, "test_copy_first_unaligned"); +} |