Re: [RFC] fs: add userspace critical mounts event support
On 03/09/2016 11:10, Dmitry Torokhov wrote: > I was thinking if we kernel could post > "conditions" (maybe simple stings) that it waits for, and userspace > could unlock these "conditions". One of them might be "firmware > available". On idea offered by Josh Triplett that seems to overlap with this one is to have something similar to the (deprecated) userhelper with *per-blob* requests and notifications except for one major difference: userspace would not anymore be in charge of *providing* the blob but would instead only *signal* when a given blob becomes available and is either found or found missing. Then the kernel loads the blob _by itself_; unlike the userhelper. No new “critical filesystem” concept and a *per-blob basis*, allowing any variation of blob locations across any number of initramfs and filesystems. Could this one fly?
[PATCH] crypto: sha1-powerpc: little-endian support
The driver does not handle endianness properly when loading the input data. Signed-off-by: Marcelo Cerri--- arch/powerpc/crypto/sha1-powerpc-asm.S | 13 +++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/crypto/sha1-powerpc-asm.S b/arch/powerpc/crypto/sha1-powerpc-asm.S index 125e165..82ddc9b 100644 --- a/arch/powerpc/crypto/sha1-powerpc-asm.S +++ b/arch/powerpc/crypto/sha1-powerpc-asm.S @@ -7,6 +7,15 @@ #include #include +#ifdef __BIG_ENDIAN__ +#define LWZ(rt, d, ra) \ + lwz rt,d(ra) +#else +#define LWZ(rt, d, ra) \ + li rt,d; \ + lwbrx rt,rt,ra +#endif + /* * We roll the registers for T, A, B, C, D, E around on each * iteration; T on iteration t is A on iteration t+1, and so on. @@ -23,7 +32,7 @@ #define W(t) (((t)%16)+16) #define LOADW(t) \ - lwz W(t),(t)*4(r4) + LWZ(W(t),(t)*4,r4) #define STEPD0_LOAD(t) \ andcr0,RD(t),RB(t); \ @@ -33,7 +42,7 @@ add r0,RE(t),r15; \ add RT(t),RT(t),r6; \ add r14,r0,W(t);\ - lwz W((t)+4),((t)+4)*4(r4); \ + LWZ(W((t)+4),((t)+4)*4,r4); \ rotlwi RB(t),RB(t),30; \ add RT(t),RT(t),r14 -- 2.7.4
[powerpc:test 88/124] arch/powerpc/kernel/exceptions-64s.S:1493: Error: attempt to move .org backwards
Hi Nicholas, First bad commit (maybe != root cause): tree: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git test head: 6f13ef67fa45546813f6a7f798d95a27ba469f29 commit: 5bbf2094b13af5f9253a607681a51e27de249ab8 [88/124] powerpc/64s: consolidate Machine Check 0x200 interrupt config: powerpc-g5_defconfig (attached as .config) compiler: powerpc64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705 reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross git checkout 5bbf2094b13af5f9253a607681a51e27de249ab8 # save the attached .config to linux build tree make.cross ARCH=powerpc Note: the powerpc/test HEAD 6f13ef67fa45546813f6a7f798d95a27ba469f29 builds fine. It only hurts bisectibility. All errors (new ones prefixed by >>): arch/powerpc/kernel/exceptions-64s.S: Assembler messages: >> arch/powerpc/kernel/exceptions-64s.S:1493: Error: attempt to move .org >> backwards vim +1493 arch/powerpc/kernel/exceptions-64s.S 087aa036 Chen Gang 2013-03-25 1487 ld r10,_LINK(r1) /* make idle task do the */ 087aa036 Chen Gang 2013-03-25 1488 std r10,_NIP(r1) /* equivalent of a blr */ 087aa036 Chen Gang 2013-03-25 1489 blr 00f29fdb Nicholas Piggin 2016-09-21 1490 TRAMP_HANDLER_END(power4_fixup_nap) 087aa036 Chen Gang 2013-03-25 1491 #endif 087aa036 Chen Gang 2013-03-25 1492 fe06bbba Nicholas Piggin 2016-09-21 @1493 CLOSE_FIXED_SECTION(real_vectors); fe06bbba Nicholas Piggin 2016-09-21 1494 CLOSE_FIXED_SECTION(real_trampolines); fe06bbba Nicholas Piggin 2016-09-21 1495 CLOSE_FIXED_SECTION(virt_vectors); fe06bbba Nicholas Piggin 2016-09-21 1496 CLOSE_FIXED_SECTION(virt_trampolines); :: The code at line 1493 was first introduced by commit :: fe06bbbaa8c7b8b2600e08af1aeb105e6f0c10f3 powerpc/64: use gas sections for arranging exception vectors :: TO: Nicholas Piggin:: CC: Michael Ellerman --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: application/gzip
[bug] crypto/vmx/p8_ghash memory corruption in 4.8-rc7
Hi, I'm chasing a memory corruption with 4.8-rc7 as I'm observing random Oopses on ppc BE/LE systems (lpars, KVM guests). About 30% of issues is that module list gets corrupted, and "cat /proc/modules" or "lsmod" triggers an Oops, for example: [ 88.486041] Unable to handle kernel paging request for data at address 0x0020 ... [ 88.487658] NIP [c020f820] m_show+0xa0/0x240 [ 88.487689] LR [c020f834] m_show+0xb4/0x240 [ 88.487719] Call Trace: [ 88.487736] [c004b605bbb0] [c020f834] m_show+0xb4/0x240 (unreliable) [ 88.487796] [c004b605bc50] [c045e73c] seq_read+0x36c/0x520 [ 88.487843] [c004b605bcf0] [c04e1014] proc_reg_read+0x84/0x120 [ 88.487889] [c004b605bd30] [c040df88] vfs_read+0xf8/0x380 [ 88.487934] [c004b605bde0] [c040fd40] SyS_read+0x60/0x110 [ 88.487981] [c004b605be30] [c0009590] system_call+0x38/0xec 0x20 offset is module_use->source, module_use is NULL because module.source_list gets corrupted. The source of corruption appears to originate from a 'ahash' test for p8_ghash: cryptomgr_test alg_test alg_test_hash test_hash __test_hash ahash_partial_update shash_async_export memcpy With some extra traces [1], I'm seeing that ahash_partial_update() allocates 56 bytes for 'state', and then crypto_ahash_export() writes 76 bytes into it: [5.970887] __test_hash alg name p8_ghash, result: c4333ac0, key: c004b860a500, req: c004b860a380 [5.970963] state: c4333f00, statesize: 56 [5.970995] shash_default_export memcpy c4333f00 c004b860a3e0, len: 76 This seems to directly correspond with: p8_ghash_alg.descsize = sizeof(struct p8_ghash_desc_ctx) == 56 shash_tfm->descsize = sizeof(struct p8_ghash_desc_ctx) + crypto_shash_descsize(fallback) == 56 + 20 where 20 is presumably coming from "ghash_alg.descsize". My gut feeling was that these 2 should match, but I'd love to hear what crypto people think. Thank you, Jan [1] diff --git a/crypto/shash.c b/crypto/shash.c index a051541..49fe182 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -188,6 +188,8 @@ EXPORT_SYMBOL_GPL(crypto_shash_digest); static int shash_default_export(struct shash_desc *desc, void *out) { + int len = crypto_shash_descsize(desc->tfm); + printk("shash_default_export memcpy %p %p, len: %d\n", out, shash_desc_ctx(desc), len); memcpy(out, shash_desc_ctx(desc), crypto_shash_descsize(desc->tfm)); return 0; } diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 5c9d5a5..2e54579 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -218,6 +218,8 @@ static int ahash_partial_update(struct ahash_request **preq, pr_err("alt: hash: Failed to alloc state for %s\n", algo); goto out_nostate; } + printk("state: %p, statesize: %d\n", state, statesize); + ret = crypto_ahash_export(req, state); if (ret) { pr_err("alt: hash: Failed to export() for %s\n", algo); @@ -288,6 +290,7 @@ static int __test_hash(struct crypto_ahash *tfm, struct hash_testvec *template, "%s\n", algo); goto out_noreq; } + printk("__test_hash alg name %s, result: %p, key: %p, req: %p\n", algo, result, key, req); ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, tcrypt_complete, );
Re: [PATCH 2/3] bpf powerpc: implement support for tail calls
On 09/23/2016 10:35 PM, Naveen N. Rao wrote: Tail calls allow JIT'ed eBPF programs to call into other JIT'ed eBPF programs. This can be achieved either by: (1) retaining the stack setup by the first eBPF program and having all subsequent eBPF programs re-using it, or, (2) by unwinding/tearing down the stack and having each eBPF program deal with its own stack as it sees fit. To ensure that this does not create loops, there is a limit to how many tail calls can be done (currently 32). This requires the JIT'ed code to maintain a count of the number of tail calls done so far. Approach (1) is simple, but requires every eBPF program to have (almost) the same prologue/epilogue, regardless of whether they need it. This is inefficient for small eBPF programs which may not sometimes need a prologue at all. As such, to minimize impact of tail call implementation, we use approach (2) here which needs each eBPF program in the chain to use its own prologue/epilogue. This is not ideal when many tail calls are involved and when all the eBPF programs in the chain have similar prologue/epilogue. However, the impact is restricted to programs that do tail calls. Individual eBPF programs are not affected. We maintain the tail call count in a fixed location on the stack and updated tail call count values are passed in through this. The very first eBPF program in a chain sets this up to 0 (the first 2 instructions). Subsequent tail calls skip the first two eBPF JIT instructions to maintain the count. For programs that don't do tail calls themselves, the first two instructions are NOPs. Signed-off-by: Naveen N. RaoThanks for adding support, Naveen, that's really great! I think 2) seems fine as well in this context as prologue size can vary quite a bit here, and depending on program types likelihood of tail call usage as well (but I wouldn't expect deep nesting). Thanks a lot!
Re: [PATCH 3/3] bpf powerpc: add support for bpf constant blinding
On 09/23/2016 10:35 PM, Naveen N. Rao wrote: In line with similar support for other architectures by Daniel Borkmann. 'MOD Default X' from test_bpf without constant blinding: 84 bytes emitted from JIT compiler (pass:3, flen:7) d58a4688 + : 0: nop 4: nop 8: std r27,-40(r1) c: std r28,-32(r1) 10: xor r8,r8,r8 14: xor r28,r28,r28 18: mr r27,r3 1c: li r8,66 20: cmpwi r28,0 24: bne 0x0030 28: li r8,0 2c: b 0x0044 30: divwu r9,r8,r28 34: mullw r9,r28,r9 38: subfr8,r9,r8 3c: rotlwi r8,r8,0 40: li r8,66 44: ld r27,-40(r1) 48: ld r28,-32(r1) 4c: mr r3,r8 50: blr ... and with constant blinding: 140 bytes emitted from JIT compiler (pass:3, flen:11) dbd6ab24 + : 0: nop 4: nop 8: std r27,-40(r1) c: std r28,-32(r1) 10: xor r8,r8,r8 14: xor r28,r28,r28 18: mr r27,r3 1c: lis r2,-22834 20: ori r2,r2,36083 24: rotlwi r2,r2,0 28: xorir2,r2,36017 2c: xoris r2,r2,42702 30: rotlwi r2,r2,0 34: mr r8,r2 38: rotlwi r8,r8,0 3c: cmpwi r28,0 40: bne 0x004c 44: li r8,0 48: b 0x007c 4c: divwu r9,r8,r28 50: mullw r9,r28,r9 54: subfr8,r9,r8 58: rotlwi r8,r8,0 5c: lis r2,-17137 60: ori r2,r2,39065 64: rotlwi r2,r2,0 68: xorir2,r2,39131 6c: xoris r2,r2,48399 70: rotlwi r2,r2,0 74: mr r8,r2 78: rotlwi r8,r8,0 7c: ld r27,-40(r1) 80: ld r28,-32(r1) 84: mr r3,r8 88: blr Signed-off-by: Naveen N. RaoAcked-by: Daniel Borkmann
[PATCH 2/2] bpf samples: update tracex5 sample to use __seccomp_filter
seccomp_phase1() does not exist anymore. Instead, update sample to use __seccomp_filter(). While at it, set max locked memory to unlimited. Signed-off-by: Naveen N. Rao--- I am not completely sure if __seccomp_filter is the right place to hook in. This works for me though. Please review. Thanks, Naveen samples/bpf/tracex5_kern.c | 16 +++- samples/bpf/tracex5_user.c | 3 +++ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/samples/bpf/tracex5_kern.c b/samples/bpf/tracex5_kern.c index f95f232..fd12d71 100644 --- a/samples/bpf/tracex5_kern.c +++ b/samples/bpf/tracex5_kern.c @@ -19,20 +19,18 @@ struct bpf_map_def SEC("maps") progs = { .max_entries = 1024, }; -SEC("kprobe/seccomp_phase1") +SEC("kprobe/__seccomp_filter") int bpf_prog1(struct pt_regs *ctx) { - struct seccomp_data sd; - - bpf_probe_read(, sizeof(sd), (void *)PT_REGS_PARM1(ctx)); + int sc_nr = (int)PT_REGS_PARM1(ctx); /* dispatch into next BPF program depending on syscall number */ - bpf_tail_call(ctx, , sd.nr); + bpf_tail_call(ctx, , sc_nr); /* fall through -> unknown syscall */ - if (sd.nr >= __NR_getuid && sd.nr <= __NR_getsid) { + if (sc_nr >= __NR_getuid && sc_nr <= __NR_getsid) { char fmt[] = "syscall=%d (one of get/set uid/pid/gid)\n"; - bpf_trace_printk(fmt, sizeof(fmt), sd.nr); + bpf_trace_printk(fmt, sizeof(fmt), sc_nr); } return 0; } @@ -42,7 +40,7 @@ PROG(__NR_write)(struct pt_regs *ctx) { struct seccomp_data sd; - bpf_probe_read(, sizeof(sd), (void *)PT_REGS_PARM1(ctx)); + bpf_probe_read(, sizeof(sd), (void *)PT_REGS_PARM2(ctx)); if (sd.args[2] == 512) { char fmt[] = "write(fd=%d, buf=%p, size=%d)\n"; bpf_trace_printk(fmt, sizeof(fmt), @@ -55,7 +53,7 @@ PROG(__NR_read)(struct pt_regs *ctx) { struct seccomp_data sd; - bpf_probe_read(, sizeof(sd), (void *)PT_REGS_PARM1(ctx)); + bpf_probe_read(, sizeof(sd), (void *)PT_REGS_PARM2(ctx)); if (sd.args[2] > 128 && sd.args[2] <= 1024) { char fmt[] = "read(fd=%d, buf=%p, size=%d)\n"; bpf_trace_printk(fmt, sizeof(fmt), diff --git a/samples/bpf/tracex5_user.c b/samples/bpf/tracex5_user.c index a04dd3c..36b5925 100644 --- a/samples/bpf/tracex5_user.c +++ b/samples/bpf/tracex5_user.c @@ -6,6 +6,7 @@ #include #include "libbpf.h" #include "bpf_load.h" +#include /* install fake seccomp program to enable seccomp code path inside the kernel, * so that our kprobe attached to seccomp_phase1() can be triggered @@ -27,8 +28,10 @@ int main(int ac, char **argv) { FILE *f; char filename[256]; + struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); + setrlimit(RLIMIT_MEMLOCK, ); if (load_bpf_file(filename)) { printf("%s", bpf_log_buf); -- 2.9.3
[PATCH 1/2] bpf samples: fix compiler errors with sockex2 and sockex3
These samples fail to compile as 'struct flow_keys' conflicts with definition in net/flow_dissector.h. Fix the same by renaming the structure used in the sample. Signed-off-by: Naveen N. Rao--- samples/bpf/sockex2_kern.c | 10 +- samples/bpf/sockex3_kern.c | 8 samples/bpf/sockex3_user.c | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/samples/bpf/sockex2_kern.c b/samples/bpf/sockex2_kern.c index ba0e177..44e5846 100644 --- a/samples/bpf/sockex2_kern.c +++ b/samples/bpf/sockex2_kern.c @@ -14,7 +14,7 @@ struct vlan_hdr { __be16 h_vlan_encapsulated_proto; }; -struct flow_keys { +struct bpf_flow_keys { __be32 src; __be32 dst; union { @@ -59,7 +59,7 @@ static inline __u32 ipv6_addr_hash(struct __sk_buff *ctx, __u64 off) } static inline __u64 parse_ip(struct __sk_buff *skb, __u64 nhoff, __u64 *ip_proto, -struct flow_keys *flow) +struct bpf_flow_keys *flow) { __u64 verlen; @@ -83,7 +83,7 @@ static inline __u64 parse_ip(struct __sk_buff *skb, __u64 nhoff, __u64 *ip_proto } static inline __u64 parse_ipv6(struct __sk_buff *skb, __u64 nhoff, __u64 *ip_proto, - struct flow_keys *flow) + struct bpf_flow_keys *flow) { *ip_proto = load_byte(skb, nhoff + offsetof(struct ipv6hdr, nexthdr)); @@ -96,7 +96,7 @@ static inline __u64 parse_ipv6(struct __sk_buff *skb, __u64 nhoff, __u64 *ip_pro return nhoff; } -static inline bool flow_dissector(struct __sk_buff *skb, struct flow_keys *flow) +static inline bool flow_dissector(struct __sk_buff *skb, struct bpf_flow_keys *flow) { __u64 nhoff = ETH_HLEN; __u64 ip_proto; @@ -198,7 +198,7 @@ struct bpf_map_def SEC("maps") hash_map = { SEC("socket2") int bpf_prog2(struct __sk_buff *skb) { - struct flow_keys flow; + struct bpf_flow_keys flow; struct pair *value; u32 key; diff --git a/samples/bpf/sockex3_kern.c b/samples/bpf/sockex3_kern.c index 41ae2fd..95907f8 100644 --- a/samples/bpf/sockex3_kern.c +++ b/samples/bpf/sockex3_kern.c @@ -61,7 +61,7 @@ struct vlan_hdr { __be16 h_vlan_encapsulated_proto; }; -struct flow_keys { +struct bpf_flow_keys { __be32 src; __be32 dst; union { @@ -88,7 +88,7 @@ static inline __u32 ipv6_addr_hash(struct __sk_buff *ctx, __u64 off) } struct globals { - struct flow_keys flow; + struct bpf_flow_keys flow; }; struct bpf_map_def SEC("maps") percpu_map = { @@ -114,14 +114,14 @@ struct pair { struct bpf_map_def SEC("maps") hash_map = { .type = BPF_MAP_TYPE_HASH, - .key_size = sizeof(struct flow_keys), + .key_size = sizeof(struct bpf_flow_keys), .value_size = sizeof(struct pair), .max_entries = 1024, }; static void update_stats(struct __sk_buff *skb, struct globals *g) { - struct flow_keys key = g->flow; + struct bpf_flow_keys key = g->flow; struct pair *value; value = bpf_map_lookup_elem(_map, ); diff --git a/samples/bpf/sockex3_user.c b/samples/bpf/sockex3_user.c index d4184ab..3fcfd8c4 100644 --- a/samples/bpf/sockex3_user.c +++ b/samples/bpf/sockex3_user.c @@ -7,7 +7,7 @@ #include #include -struct flow_keys { +struct bpf_flow_keys { __be32 src; __be32 dst; union { @@ -49,7 +49,7 @@ int main(int argc, char **argv) (void) f; for (i = 0; i < 5; i++) { - struct flow_keys key = {}, next_key; + struct bpf_flow_keys key = {}, next_key; struct pair value; sleep(1); -- 2.9.3
[PATCH 3/3] bpf powerpc: add support for bpf constant blinding
In line with similar support for other architectures by Daniel Borkmann. 'MOD Default X' from test_bpf without constant blinding: 84 bytes emitted from JIT compiler (pass:3, flen:7) d58a4688 + : 0: nop 4: nop 8: std r27,-40(r1) c: std r28,-32(r1) 10: xor r8,r8,r8 14: xor r28,r28,r28 18: mr r27,r3 1c: li r8,66 20: cmpwi r28,0 24: bne 0x0030 28: li r8,0 2c: b 0x0044 30: divwu r9,r8,r28 34: mullw r9,r28,r9 38: subfr8,r9,r8 3c: rotlwi r8,r8,0 40: li r8,66 44: ld r27,-40(r1) 48: ld r28,-32(r1) 4c: mr r3,r8 50: blr ... and with constant blinding: 140 bytes emitted from JIT compiler (pass:3, flen:11) dbd6ab24 + : 0: nop 4: nop 8: std r27,-40(r1) c: std r28,-32(r1) 10: xor r8,r8,r8 14: xor r28,r28,r28 18: mr r27,r3 1c: lis r2,-22834 20: ori r2,r2,36083 24: rotlwi r2,r2,0 28: xorir2,r2,36017 2c: xoris r2,r2,42702 30: rotlwi r2,r2,0 34: mr r8,r2 38: rotlwi r8,r8,0 3c: cmpwi r28,0 40: bne 0x004c 44: li r8,0 48: b 0x007c 4c: divwu r9,r8,r28 50: mullw r9,r28,r9 54: subfr8,r9,r8 58: rotlwi r8,r8,0 5c: lis r2,-17137 60: ori r2,r2,39065 64: rotlwi r2,r2,0 68: xorir2,r2,39131 6c: xoris r2,r2,48399 70: rotlwi r2,r2,0 74: mr r8,r2 78: rotlwi r8,r8,0 7c: ld r27,-40(r1) 80: ld r28,-32(r1) 84: mr r3,r8 88: blr Signed-off-by: Naveen N. Rao--- arch/powerpc/net/bpf_jit64.h | 9 + arch/powerpc/net/bpf_jit_comp64.c | 36 +--- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/arch/powerpc/net/bpf_jit64.h b/arch/powerpc/net/bpf_jit64.h index 038e00b..62fa758 100644 --- a/arch/powerpc/net/bpf_jit64.h +++ b/arch/powerpc/net/bpf_jit64.h @@ -39,10 +39,10 @@ #ifndef __ASSEMBLY__ /* BPF register usage */ -#define SKB_HLEN_REG (MAX_BPF_REG + 0) -#define SKB_DATA_REG (MAX_BPF_REG + 1) -#define TMP_REG_1 (MAX_BPF_REG + 2) -#define TMP_REG_2 (MAX_BPF_REG + 3) +#define SKB_HLEN_REG (MAX_BPF_JIT_REG + 0) +#define SKB_DATA_REG (MAX_BPF_JIT_REG + 1) +#define TMP_REG_1 (MAX_BPF_JIT_REG + 2) +#define TMP_REG_2 (MAX_BPF_JIT_REG + 3) /* BPF to ppc register mappings */ static const int b2p[] = { @@ -62,6 +62,7 @@ static const int b2p[] = { /* frame pointer aka BPF_REG_10 */ [BPF_REG_FP] = 31, /* eBPF jit internal registers */ + [BPF_REG_AX] = 2, [SKB_HLEN_REG] = 25, [SKB_DATA_REG] = 26, [TMP_REG_1] = 9, diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c index 3ec29d6..0fe98a5 100644 --- a/arch/powerpc/net/bpf_jit_comp64.c +++ b/arch/powerpc/net/bpf_jit_comp64.c @@ -974,21 +974,37 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) int pass; int flen; struct bpf_binary_header *bpf_hdr; + struct bpf_prog *org_fp = fp; + struct bpf_prog *tmp_fp; + bool bpf_blinded = false; if (!bpf_jit_enable) - return fp; + return org_fp; + + tmp_fp = bpf_jit_blind_constants(org_fp); + if (IS_ERR(tmp_fp)) + return org_fp; + + if (tmp_fp != org_fp) { + bpf_blinded = true; + fp = tmp_fp; + } flen = fp->len; addrs = kzalloc((flen+1) * sizeof(*addrs), GFP_KERNEL); - if (addrs == NULL) - return fp; + if (addrs == NULL) { + fp = org_fp; + goto out; + } + + memset(, 0, sizeof(struct codegen_context)); - cgctx.idx = 0; - cgctx.seen = 0; /* Scouting faux-generate pass 0 */ - if (bpf_jit_build_body(fp, 0, , addrs)) + if (bpf_jit_build_body(fp, 0, , addrs)) { /* We hit something illegal or unsupported. */ + fp = org_fp; goto out; + } /* * Pretend to build prologue, given the features we've seen. This will @@ -1003,8 +1019,10 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) bpf_hdr = bpf_jit_binary_alloc(alloclen, , 4, bpf_jit_fill_ill_insns); - if (!bpf_hdr) + if (!bpf_hdr) { + fp = org_fp; goto out; + } code_base = (u32 *)(image + FUNCTION_DESCR_SIZE); @@ -1041,6 +1059,10 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) out: kfree(addrs); + + if (bpf_blinded) + bpf_jit_prog_release_other(fp, fp == org_fp ? tmp_fp : org_fp); + return fp; } -- 2.9.3
[PATCH 2/3] bpf powerpc: implement support for tail calls
Tail calls allow JIT'ed eBPF programs to call into other JIT'ed eBPF programs. This can be achieved either by: (1) retaining the stack setup by the first eBPF program and having all subsequent eBPF programs re-using it, or, (2) by unwinding/tearing down the stack and having each eBPF program deal with its own stack as it sees fit. To ensure that this does not create loops, there is a limit to how many tail calls can be done (currently 32). This requires the JIT'ed code to maintain a count of the number of tail calls done so far. Approach (1) is simple, but requires every eBPF program to have (almost) the same prologue/epilogue, regardless of whether they need it. This is inefficient for small eBPF programs which may not sometimes need a prologue at all. As such, to minimize impact of tail call implementation, we use approach (2) here which needs each eBPF program in the chain to use its own prologue/epilogue. This is not ideal when many tail calls are involved and when all the eBPF programs in the chain have similar prologue/epilogue. However, the impact is restricted to programs that do tail calls. Individual eBPF programs are not affected. We maintain the tail call count in a fixed location on the stack and updated tail call count values are passed in through this. The very first eBPF program in a chain sets this up to 0 (the first 2 instructions). Subsequent tail calls skip the first two eBPF JIT instructions to maintain the count. For programs that don't do tail calls themselves, the first two instructions are NOPs. Signed-off-by: Naveen N. Rao--- arch/powerpc/include/asm/ppc-opcode.h | 2 + arch/powerpc/net/bpf_jit.h| 2 + arch/powerpc/net/bpf_jit64.h | 1 + arch/powerpc/net/bpf_jit_comp64.c | 149 +++--- 4 files changed, 126 insertions(+), 28 deletions(-) diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 127ebf5..54ff8ce 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h @@ -236,6 +236,7 @@ #define PPC_INST_STWU 0x9400 #define PPC_INST_MFLR 0x7c0802a6 #define PPC_INST_MTLR 0x7c0803a6 +#define PPC_INST_MTCTR 0x7c0903a6 #define PPC_INST_CMPWI 0x2c00 #define PPC_INST_CMPDI 0x2c20 #define PPC_INST_CMPW 0x7c00 @@ -250,6 +251,7 @@ #define PPC_INST_SUB 0x7c50 #define PPC_INST_BLR 0x4e800020 #define PPC_INST_BLRL 0x4e800021 +#define PPC_INST_BCTR 0x4e800420 #define PPC_INST_MULLD 0x7c0001d2 #define PPC_INST_MULLW 0x7c0001d6 #define PPC_INST_MULHWU0x7c16 diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h index d5301b6..89f7007 100644 --- a/arch/powerpc/net/bpf_jit.h +++ b/arch/powerpc/net/bpf_jit.h @@ -40,6 +40,8 @@ #define PPC_BLR() EMIT(PPC_INST_BLR) #define PPC_BLRL() EMIT(PPC_INST_BLRL) #define PPC_MTLR(r)EMIT(PPC_INST_MTLR | ___PPC_RT(r)) +#define PPC_BCTR() EMIT(PPC_INST_BCTR) +#define PPC_MTCTR(r) EMIT(PPC_INST_MTCTR | ___PPC_RT(r)) #define PPC_ADDI(d, a, i) EMIT(PPC_INST_ADDI | ___PPC_RT(d) | \ ___PPC_RA(a) | IMM_L(i)) #define PPC_MR(d, a) PPC_OR(d, a, a) diff --git a/arch/powerpc/net/bpf_jit64.h b/arch/powerpc/net/bpf_jit64.h index a1645d7..038e00b 100644 --- a/arch/powerpc/net/bpf_jit64.h +++ b/arch/powerpc/net/bpf_jit64.h @@ -88,6 +88,7 @@ DECLARE_LOAD_FUNC(sk_load_byte); #define SEEN_FUNC 0x1000 /* might call external helpers */ #define SEEN_STACK 0x2000 /* uses BPF stack */ #define SEEN_SKB 0x4000 /* uses sk_buff */ +#define SEEN_TAILCALL 0x8000 /* uses tail calls */ struct codegen_context { /* diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c index 5f8c91f..3ec29d6 100644 --- a/arch/powerpc/net/bpf_jit_comp64.c +++ b/arch/powerpc/net/bpf_jit_comp64.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "bpf_jit64.h" @@ -77,6 +78,11 @@ static int bpf_jit_stack_local(struct codegen_context *ctx) return -(BPF_PPC_STACK_SAVE + 16); } +static int bpf_jit_stack_tailcallcnt(struct codegen_context *ctx) +{ + return bpf_jit_stack_local(ctx) + 8; +} + static int bpf_jit_stack_offsetof(struct codegen_context *ctx, int reg) { if (reg >= BPF_PPC_NVR_MIN && reg < 32) @@ -102,33 +108,25 @@ static void bpf_jit_emit_skb_loads(u32 *image, struct codegen_context *ctx) PPC_BPF_LL(b2p[SKB_DATA_REG], 3, offsetof(struct sk_buff, data)); } -static void bpf_jit_emit_func_call(u32 *image, struct codegen_context *ctx, u64 func) +static void bpf_jit_build_prologue(u32 *image, struct
[PATCH 1/3] bpf powerpc: introduce accessors for using the tmp local stack space
While at it, ensure that the location of the local save area is consistent whether or not we setup our own stackframe. This property is utilised in the next patch that adds support for tail calls. Signed-off-by: Naveen N. Rao--- arch/powerpc/net/bpf_jit64.h | 16 +--- arch/powerpc/net/bpf_jit_comp64.c | 79 ++- 2 files changed, 55 insertions(+), 40 deletions(-) diff --git a/arch/powerpc/net/bpf_jit64.h b/arch/powerpc/net/bpf_jit64.h index 5046d6f..a1645d7 100644 --- a/arch/powerpc/net/bpf_jit64.h +++ b/arch/powerpc/net/bpf_jit64.h @@ -16,22 +16,25 @@ /* * Stack layout: + * Ensure the top half (upto local_tmp_var) stays consistent + * with our redzone usage. * * [ prev sp ] <- * [ nv gpr save area] 8*8 | + * [tail_call_cnt ] 8 | + * [local_tmp_var ] 8 | * fp (r31) -->[ ebpf stack space] 512 | - * [ local/tmp var space ] 16| * [ frame header ] 32/112| * sp (r1) --->[stack pointer ] -- */ -/* for bpf JIT code internal usage */ -#define BPF_PPC_STACK_LOCALS 16 /* for gpr non volatile registers BPG_REG_6 to 10, plus skb cache registers */ #define BPF_PPC_STACK_SAVE (8*8) +/* for bpf JIT code internal usage */ +#define BPF_PPC_STACK_LOCALS 16 /* Ensure this is quadword aligned */ -#define BPF_PPC_STACKFRAME (STACK_FRAME_MIN_SIZE + BPF_PPC_STACK_LOCALS + \ -MAX_BPF_STACK + BPF_PPC_STACK_SAVE) +#define BPF_PPC_STACKFRAME (STACK_FRAME_MIN_SIZE + MAX_BPF_STACK + \ +BPF_PPC_STACK_LOCALS + BPF_PPC_STACK_SAVE) #ifndef __ASSEMBLY__ @@ -65,6 +68,9 @@ static const int b2p[] = { [TMP_REG_2] = 10 }; +/* PPC NVR range -- update this if we ever use NVRs below r24 */ +#define BPF_PPC_NVR_MIN24 + /* Assembly helpers */ #define DECLARE_LOAD_FUNC(func)u64 func(u64 r3, u64 r4); \ u64 func##_negative_offset(u64 r3, u64 r4); \ diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c index 6073b78..5f8c91f 100644 --- a/arch/powerpc/net/bpf_jit_comp64.c +++ b/arch/powerpc/net/bpf_jit_comp64.c @@ -58,6 +58,35 @@ static inline bool bpf_has_stack_frame(struct codegen_context *ctx) return ctx->seen & SEEN_FUNC || bpf_is_seen_register(ctx, BPF_REG_FP); } +/* + * When not setting up our own stackframe, the redzone usage is: + * + * [ prev sp ] <- + * [ ... ] | + * sp (r1) --->[stack pointer ] -- + * [ nv gpr save area] 8*8 + * [tail_call_cnt ] 8 + * [local_tmp_var ] 8 + * [ unused red zone ] 208 bytes protected + */ +static int bpf_jit_stack_local(struct codegen_context *ctx) +{ + if (bpf_has_stack_frame(ctx)) + return STACK_FRAME_MIN_SIZE + MAX_BPF_STACK; + else + return -(BPF_PPC_STACK_SAVE + 16); +} + +static int bpf_jit_stack_offsetof(struct codegen_context *ctx, int reg) +{ + if (reg >= BPF_PPC_NVR_MIN && reg < 32) + return (bpf_has_stack_frame(ctx) ? BPF_PPC_STACKFRAME : 0) + - (8 * (32 - reg)); + + pr_err("BPF JIT is asking about unknown registers"); + BUG(); +} + static void bpf_jit_emit_skb_loads(u32 *image, struct codegen_context *ctx) { /* @@ -100,9 +129,8 @@ static void bpf_jit_emit_func_call(u32 *image, struct codegen_context *ctx, u64 static void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx) { int i; - bool new_stack_frame = bpf_has_stack_frame(ctx); - if (new_stack_frame) { + if (bpf_has_stack_frame(ctx)) { /* * We need a stack frame, but we don't necessarily need to * save/restore LR unless we call other functions @@ -122,9 +150,7 @@ static void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx) */ for (i = BPF_REG_6; i <= BPF_REG_10; i++) if (bpf_is_seen_register(ctx, i)) - PPC_BPF_STL(b2p[i], 1, - (new_stack_frame ? BPF_PPC_STACKFRAME : 0) - - (8 * (32 - b2p[i]))); + PPC_BPF_STL(b2p[i], 1, bpf_jit_stack_offsetof(ctx, b2p[i])); /* * Save additional non-volatile regs if we cache skb @@ -132,22 +158,21 @@ static void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx) */ if (ctx->seen & SEEN_SKB) { PPC_BPF_STL(b2p[SKB_HLEN_REG], 1,
Re: [PATCH 2/2] powernv:idle:Implement lite variant of power_enter_stop
Hi Michael, On Fri, Sep 23, 2016 at 09:03:45PM +1000, Michael Ellerman wrote: > "Gautham R. Shenoy"writes: > > > From: "Gautham R. Shenoy" > > > > This patch adds a function named power_enter_stop_lite() that can > > execute a stop instruction when ESL and EC bits are set to zero in the > > PSSCR. The function handles the wake-up from idle at the instruction > > immediately after the stop instruction. > > > > If the flag OPAL_PM_WAKEUP_AT_NEXT_INST[1] is set in the device tree > > for a stop state, then use the lite variant for that particular stop > > state. > > Hi Gautham, > > It seems to me that this would be cleaner if it was modelled as a new > stop state? Surely it must have different power saving characteristics > to the existing state? It is supposed to be a new stop state, whose behaviour is different from the existing stop states in terms of where it wakes up from stop. You are right, it has different power saving characteristics to the existing state. > > > [1] : The corresponding patch in skiboot that defines > > OPAL_PM_WAKEUP_AT_NEXT_INST and enables it in the device tree > > can be found here: > > https://lists.ozlabs.org/pipermail/skiboot/2016-September/004805.html > > Which says "This will reduce the exit latency of the idle state", and > yet it doesn't change any of the latency/residency values? > > If all it does is reduce the exit latency, then shouldn't we always use > it? Presumably it also saves less power? It does save less power compared to the corresponding variant where ESL=EC=1. > > > diff --git a/arch/powerpc/kernel/idle_book3s.S > > b/arch/powerpc/kernel/idle_book3s.S > > index 32d666b..47ee106 100644 > > --- a/arch/powerpc/kernel/idle_book3s.S > > +++ b/arch/powerpc/kernel/idle_book3s.S > > @@ -43,6 +43,8 @@ > > #define PSSCR_HV_TEMPLATE PSSCR_ESL | PSSCR_EC | \ > > PSSCR_PSLL_MASK | PSSCR_TR_MASK | \ > > PSSCR_MTL_MASK > > +#define PSSCR_HV_TEMPLATE_LITE PSSCR_PSLL_MASK | PSSCR_TR_MASK | \ > > +PSSCR_MTL_MASK > > Why do we have these at all? Firmware tells us the PSSCR values to use > in the "ibm,cpu-idle-state-psscr" property. > > If we just used what firmware gave us then we wouldn't need the above, > or the juggling below. Let me rework the patch to use the cpu-idle-state-psscr property which is currently set to 0 in the firmware and cpu-idle-state-psscr-mask which is set to 0xF for all the stop states. I agree, we can do without the hardcoding of the mask in the kernel. > > > @@ -333,13 +349,19 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, > > 66); \ > > > > /* > > * r3 - requested stop state > > + * r4 - Indicates if the lite variant with ESL=EC=0 should be executed. > > */ > > _GLOBAL(power9_idle_stop) > > - LOAD_REG_IMMEDIATE(r4, PSSCR_HV_TEMPLATE) > > - or r4,r4,r3 > > + cmpdi r4, 1 > > + bne 4f > > + LOAD_REG_IMMEDIATE(r4, PSSCR_HV_TEMPLATE_LITE) > > + LOAD_REG_ADDR(r5,power_enter_stop_lite) > > + b 5f > > +4: LOAD_REG_IMMEDIATE(r4, PSSCR_HV_TEMPLATE) > > + LOAD_REG_ADDR(r5,power_enter_stop) > > +5: or r4,r4,r3 > > mtspr SPRN_PSSCR, r4 > > li r4, 1 > > - LOAD_REG_ADDR(r5,power_enter_stop) > > b pnv_powersave_common > > /* No return */ > > /* > > > diff --git a/arch/powerpc/platforms/powernv/idle.c > > b/arch/powerpc/platforms/powernv/idle.c > > index 479c256..c3d3fed 100644 > > --- a/arch/powerpc/platforms/powernv/idle.c > > +++ b/arch/powerpc/platforms/powernv/idle.c > > @@ -244,8 +244,15 @@ static DEVICE_ATTR(fastsleep_workaround_applyonce, > > 0600, > > static void power9_idle(void) > > { > > /* Requesting stop state 0 */ > > - power9_idle_stop(0); > > } > > That seems like the root of the problem, why aren't we passing a PSSCR > value here? > > I also don't see us using the psscr-mask property anywhere. Why isn't > that a bug? Because we are only setting the Requested Level field which is the bottom 4 bits. Everything else is taken from the hardcoded mask, which is not incorrect, but not a very flexible design. Thanks for the comments Michael. I will come back with a cleaner patch. > > cheers > -- Thanks and Regards gautham.
ehea crash on boot
Heh, another thing to debug :) mm: Hashing failure ! EA=0xd80080124040 access=0x800e current=NetworkManager trap=0x300 vsid=0x13d349c ssize=1 base psize=2 psize 2 pte=0xc0003bc0300301ae mm: Hashing failure ! EA=0xd80080124040 access=0x800e current=NetworkManager trap=0x300 vsid=0x13d349c ssize=1 base psize=2 psize 2 pte=0xc0003bc0300301ae Unable to handle kernel paging request for data at address 0xd80080124040 Faulting instruction address: 0xc06f21a0 cpu 0x8: Vector: 300 (Data Access) at [c005a8b92b50] pc: c06f21a0: .ehea_create_cq+0x160/0x230 lr: c06f2164: .ehea_create_cq+0x124/0x230 sp: c005a8b92dd0 msr: 80009032 dar: d80080124040 dsisr: 4200 current = 0xc005a8b68200 paca = 0xcea94000 softe: 0 irq_happened: 0x01 pid = 6787, comm = NetworkManager Linux version 4.8.0-rc6-00214-g4cea877 (kda@ps700) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC) ) #1 SMP Fri Sep 23 15:01:08 MSK 2016 enter ? for help [c005a8b92dd0] c06f2140 .ehea_create_cq+0x100/0x230 (unreliable) [c005a8b92e70] c06ed448 .ehea_up+0x288/0xed0 [c005a8b92fe0] c06ee314 .ehea_open+0x44/0x130 [c005a8b93070] c0812324 .__dev_open+0x154/0x220 [c005a8b93110] c0812734 .__dev_change_flags+0xd4/0x1e0 [c005a8b931b0] c081286c .dev_change_flags+0x2c/0x80 [c005a8b93240] c0829f0c .do_setlink+0x37c/0xe50 [c005a8b933c0] c082c884 .rtnl_newlink+0x5e4/0x9b0 [c005a8b936d0] c082cd08 .rtnetlink_rcv_msg+0xb8/0x2f0 [c005a8b937a0] c084e25c .netlink_rcv_skb+0x12c/0x150 [c005a8b93830] c0829458 .rtnetlink_rcv+0x38/0x60 [c005a8b938b0] c084d814 .netlink_unicast+0x1e4/0x350 [c005a8b93960] c084def8 .netlink_sendmsg+0x418/0x480 [c005a8b93a40] c07defac .sock_sendmsg+0x2c/0x60 [c005a8b93ab0] c07e0cbc .___sys_sendmsg+0x30c/0x320 [c005a8b93c90] c07e21bc .__sys_sendmsg+0x4c/0xb0 [c005a8b93d80] c07e2dec .SyS_socketcall+0x34c/0x3d0 [c005a8b93e30] c000946c system_call+0x38/0x108
Re: [PATCH v2] powerpc/mm: export current mmu mode info
Hari Bathiniwrites: > diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h > index e2fb408..558987c 100644 > --- a/arch/powerpc/include/asm/mmu.h > +++ b/arch/powerpc/include/asm/mmu.h > @@ -199,6 +199,21 @@ static inline void mmu_clear_feature(unsigned long > feature) > > extern unsigned int __start___mmu_ftr_fixup, __stop___mmu_ftr_fixup; > > +/* > + * Possible MMU modes > + */ > +#define MMU_MODE_NONE 0 > +#define MMU_MODE_RADIX 1 > +#define MMU_MODE_HASH 2 > +#define MMU_MODE_HASH32 3 > +#define MMU_MODE_NOHASH 4 > +#define MMU_MODE_NOHASH32 5 These are already defined in the same file: /* * MMU families */ #define MMU_FTR_HPTE_TABLE ASM_CONST(0x0001) #define MMU_FTR_TYPE_8xxASM_CONST(0x0002) #define MMU_FTR_TYPE_40xASM_CONST(0x0004) #define MMU_FTR_TYPE_44xASM_CONST(0x0008) #define MMU_FTR_TYPE_FSL_E ASM_CONST(0x0010) #define MMU_FTR_TYPE_47xASM_CONST(0x0020) #define MMU_FTR_TYPE_RADIX ASM_CONST(0x0040) And the values for the current CPU are in cur_cpu_spec->mmu_features. So if you must export anything, make it that value, and hopefully the rest of the patch goes away. cheers
Re: [PATCH 2/2] powernv:idle:Implement lite variant of power_enter_stop
"Gautham R. Shenoy"writes: > From: "Gautham R. Shenoy" > > This patch adds a function named power_enter_stop_lite() that can > execute a stop instruction when ESL and EC bits are set to zero in the > PSSCR. The function handles the wake-up from idle at the instruction > immediately after the stop instruction. > > If the flag OPAL_PM_WAKEUP_AT_NEXT_INST[1] is set in the device tree > for a stop state, then use the lite variant for that particular stop > state. Hi Gautham, It seems to me that this would be cleaner if it was modelled as a new stop state? Surely it must have different power saving characteristics to the existing state? > [1] : The corresponding patch in skiboot that defines > OPAL_PM_WAKEUP_AT_NEXT_INST and enables it in the device tree > can be found here: > https://lists.ozlabs.org/pipermail/skiboot/2016-September/004805.html Which says "This will reduce the exit latency of the idle state", and yet it doesn't change any of the latency/residency values? If all it does is reduce the exit latency, then shouldn't we always use it? Presumably it also saves less power? > diff --git a/arch/powerpc/kernel/idle_book3s.S > b/arch/powerpc/kernel/idle_book3s.S > index 32d666b..47ee106 100644 > --- a/arch/powerpc/kernel/idle_book3s.S > +++ b/arch/powerpc/kernel/idle_book3s.S > @@ -43,6 +43,8 @@ > #define PSSCR_HV_TEMPLATEPSSCR_ESL | PSSCR_EC | \ > PSSCR_PSLL_MASK | PSSCR_TR_MASK | \ > PSSCR_MTL_MASK > +#define PSSCR_HV_TEMPLATE_LITE PSSCR_PSLL_MASK | PSSCR_TR_MASK | \ > + PSSCR_MTL_MASK Why do we have these at all? Firmware tells us the PSSCR values to use in the "ibm,cpu-idle-state-psscr" property. If we just used what firmware gave us then we wouldn't need the above, or the juggling below. > @@ -333,13 +349,19 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, > 66);\ > > /* > * r3 - requested stop state > + * r4 - Indicates if the lite variant with ESL=EC=0 should be executed. > */ > _GLOBAL(power9_idle_stop) > - LOAD_REG_IMMEDIATE(r4, PSSCR_HV_TEMPLATE) > - or r4,r4,r3 > + cmpdi r4, 1 > + bne 4f > + LOAD_REG_IMMEDIATE(r4, PSSCR_HV_TEMPLATE_LITE) > + LOAD_REG_ADDR(r5,power_enter_stop_lite) > + b 5f > +4: LOAD_REG_IMMEDIATE(r4, PSSCR_HV_TEMPLATE) > + LOAD_REG_ADDR(r5,power_enter_stop) > +5: or r4,r4,r3 > mtspr SPRN_PSSCR, r4 > li r4, 1 > - LOAD_REG_ADDR(r5,power_enter_stop) > b pnv_powersave_common > /* No return */ > /* > diff --git a/arch/powerpc/platforms/powernv/idle.c > b/arch/powerpc/platforms/powernv/idle.c > index 479c256..c3d3fed 100644 > --- a/arch/powerpc/platforms/powernv/idle.c > +++ b/arch/powerpc/platforms/powernv/idle.c > @@ -244,8 +244,15 @@ static DEVICE_ATTR(fastsleep_workaround_applyonce, 0600, > static void power9_idle(void) > { > /* Requesting stop state 0 */ > - power9_idle_stop(0); > } That seems like the root of the problem, why aren't we passing a PSSCR value here? I also don't see us using the psscr-mask property anywhere. Why isn't that a bug? cheers
Re: [PATCH] percpu: improve generic percpu modify-return implementation
On Thu, 22 Sep 2016 12:07:49 -0400 Tejun Heowrote: > Hello, > > On Thu, Sep 22, 2016 at 02:35:00PM +1000, Nicholas Piggin wrote: > > Well thank you, how about you? > > Heh, can't complain. Hope to see you around sometime. It's been > forever. Yeah, it has been. Hopefully I'll see you around. > > Trying a new mail client, sorry. It *seems* to be working now, how's > > this? > > Hmm... Still encoded. It looks to be a helpful surprise feature of claws. Any line starting with the word "From" make it go q-p due to some mail servers treating that differently. Sigh. > > > From d0cb9052d6f4c31d24f999b7b0cecb34681eee9b Mon Sep 17 00:00:00 2001 > > From: Nicholas Piggin > > Date: Wed, 21 Sep 2016 18:23:43 +1000 > > Subject: [PATCH] percpu: improve generic percpu modify-return > > implementations > > > > Some architectures require an additional load to find the address of > > percpu pointers. In some implemenatations, the C aliasing rules do not > > allow the result of that load to be kept over the store that modifies > > the percpu variable, which causes additional loads. > > > > Work around this by finding the pointer first, then operating on that. > > > > It's also possible to mark things as restrict and those kind of games, > > but that can require larger and arch specific changes. > > QP-decoded and applied to percpu/for-4.9. > > Thanks. > Thanks!
Re: [PATCH kernel 14/15] vfio/spapr_tce: Export container API for external users
On Wed, Sep 21, 2016 at 04:56:52PM +1000, Alexey Kardashevskiy wrote: > On 07/09/16 19:09, Alexey Kardashevskiy wrote: > > On 29/08/16 23:27, David Gibson wrote: > >> On Mon, Aug 29, 2016 at 04:35:15PM +1000, Alexey Kardashevskiy wrote: > >>> On 18/08/16 10:22, Alexey Kardashevskiy wrote: > On 17/08/16 13:17, David Gibson wrote: > > On Fri, Aug 12, 2016 at 09:22:01AM -0600, Alex Williamson wrote: > >> On Fri, 12 Aug 2016 15:46:01 +1000 > >> David Gibsonwrote: > >> > >>> On Wed, Aug 10, 2016 at 10:46:30AM -0600, Alex Williamson wrote: > On Wed, 10 Aug 2016 15:37:17 +1000 > Alexey Kardashevskiy wrote: > > > On 09/08/16 22:16, Alex Williamson wrote: > >> On Tue, 9 Aug 2016 15:19:39 +1000 > >> Alexey Kardashevskiy wrote: > >> > >>> On 09/08/16 02:43, Alex Williamson wrote: > On Wed, 3 Aug 2016 18:40:55 +1000 > Alexey Kardashevskiy wrote: > > > This exports helpers which are needed to keep a VFIO container > > in > > memory while there are external users such as KVM. > > > > Signed-off-by: Alexey Kardashevskiy > > --- > > drivers/vfio/vfio.c | 30 > > ++ > > drivers/vfio/vfio_iommu_spapr_tce.c | 16 +++- > > include/linux/vfio.h| 6 ++ > > 3 files changed, 51 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c > > index d1d70e0..baf6a9c 100644 > > --- a/drivers/vfio/vfio.c > > +++ b/drivers/vfio/vfio.c > > @@ -1729,6 +1729,36 @@ long > > vfio_external_check_extension(struct vfio_group *group, > > unsigned long arg) > > EXPORT_SYMBOL_GPL(vfio_external_check_extension); > > > > /** > > + * External user API for containers, exported by symbols to be > > linked > > + * dynamically. > > + * > > + */ > > +struct vfio_container *vfio_container_get_ext(struct file > > *filep) > > +{ > > + struct vfio_container *container = filep->private_data; > > + > > + if (filep->f_op != _fops) > > + return ERR_PTR(-EINVAL); > > + > > + vfio_container_get(container); > > + > > + return container; > > +} > > +EXPORT_SYMBOL_GPL(vfio_container_get_ext); > > + > > +void vfio_container_put_ext(struct vfio_container *container) > > +{ > > + vfio_container_put(container); > > +} > > +EXPORT_SYMBOL_GPL(vfio_container_put_ext); > > + > > +void *vfio_container_get_iommu_data_ext(struct vfio_container > > *container) > > +{ > > + return container->iommu_data; > > +} > > +EXPORT_SYMBOL_GPL(vfio_container_get_iommu_data_ext); > > + > > +/** > > * Sub-module support > > */ > > /* > > diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c > > b/drivers/vfio/vfio_iommu_spapr_tce.c > > index 3594ad3..fceea3d 100644 > > --- a/drivers/vfio/vfio_iommu_spapr_tce.c > > +++ b/drivers/vfio/vfio_iommu_spapr_tce.c > > @@ -1331,6 +1331,21 @@ const struct vfio_iommu_driver_ops > > tce_iommu_driver_ops = { > > .detach_group = tce_iommu_detach_group, > > }; > > > > +struct iommu_table > > *vfio_container_spapr_tce_table_get_ext(void *iommu_data, > > + u64 offset) > > +{ > > + struct tce_container *container = iommu_data; > > + struct iommu_table *tbl = NULL; > > + > > + if (tce_iommu_find_table(container, offset, ) < 0) > > + return NULL; > > + > > + iommu_table_get(tbl); > > + > > + return tbl; > > +} > > +EXPORT_SYMBOL_GPL(vfio_container_spapr_tce_table_get_ext); > > + > > static int __init tce_iommu_init(void) > > { > > return > > vfio_register_iommu_driver(_iommu_driver_ops); > > @@ -1348,4 +1363,3 @@ MODULE_VERSION(DRIVER_VERSION); > > MODULE_LICENSE("GPL v2"); > >
Re: [PATCH v2] powerpc/mm: export current mmu mode info
On Friday 23 September 2016 10:14 AM, Aneesh Kumar K.V wrote: Hari Bathiniwrites: Hi Aneesh, On Thursday 22 September 2016 09:54 PM, Aneesh Kumar K.V wrote: Hari Bathini writes: The kernel now supports both radix and hash MMU modes. Tools like crash and makedumpfile need to know the current MMU mode the kernel is using, to debug/analyze it. The current MMU mode depends on hardware support and also whether disable_radix cmdline parameter is passed to the kernel. The mmu_features member of cpu_spec structure holds the current MMU mode a cpu is using. But the above mentioned tools need to know the MMU mode early in their init process, when they may not have access to offset info of structure members. A hard-coded offset may help but it won't be robust. IIUC, you walk the linux page table and that should be more or less same Taking the case of crash tool, vmemmap start value is currently hard-coded to 0xf000UL but it changed to 0xc00aUL in case of radix. All of that is already defined as variables in the kernel. You can look at radix__early_init_mmu(). between radix/hash right except few bits. Now what crash will be interested in will be the RPN part of the table which should be same between hash/radix. Though the walk is pretty much the same, the tool still needs to know the right index values and vmemmap start to use, as they are different for radix and hash.. This patch introduces a new global variable, which holds the current MMU mode the kernel is running in and can be accessed by tools early in thier init process, Init process of what ? kernel or crash tool ? tool initialization - crash or makedumpfile.. helping tools to initialize accurately for each MMU mode. This patch also optimizes the radix_enabled() function call. how do you differentiate between the hold linux page table format and the new ? Can you also summarize what crash tool look for in the page table ? It needs the index sizes, masked bit values and page flag info to do the page table walk. Since they can be different for hash and radix.. Can you look at radix__early_init_mmu/hash__early_init_mmu and see you can work with the variables defined there ? Did consider that but didn't opt for it for a few reasons: 1. Will still need to know the MMU mode as huge page address translation is not the same for radix & hash. 2. Will have to get all these values from a crashed kernel when I can set them based on MMU mode. Less dependence on the failed kernel, the better.. 3. Stash more variables in vmcoreinfo (for makedumpfile) when one is sufficient to serve the purpose. Thanks Hari
[PATCH v5 17/20] selftests/powerpc: Add checks for transactional VSXs in signal contexts
If a thread receives a signal while transactional the kernel creates a second context to show the transactional state of the process. This test loads some known values and waits for a signal and confirms that the expected values are in the signal context. Signed-off-by: Cyril Bur--- tools/testing/selftests/powerpc/tm/Makefile| 2 +- .../powerpc/tm/tm-signal-context-chk-vsx.c | 125 + 2 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile index 06c44aa..9d53f8b 100644 --- a/tools/testing/selftests/powerpc/tm/Makefile +++ b/tools/testing/selftests/powerpc/tm/Makefile @@ -1,5 +1,5 @@ SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr tm-signal-context-chk-fpu \ - tm-signal-context-chk-vmx + tm-signal-context-chk-vmx tm-signal-context-chk-vsx TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \ tm-vmxcopy tm-fork tm-tar tm-tmspr $(SIGNAL_CONTEXT_CHK_TESTS) diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c new file mode 100644 index 000..b99c3d8 --- /dev/null +++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c @@ -0,0 +1,125 @@ +/* + * Copyright 2016, Cyril Bur, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * + * Test the kernel's signal frame code. + * + * The kernel sets up two sets of ucontexts if the signal was to be + * delivered while the thread was in a transaction. + * Expected behaviour is that the checkpointed state is in the user + * context passed to the signal handler. The speculated state can be + * accessed with the uc_link pointer. + * + * The rationale for this is that if TM unaware code (which linked + * against TM libs) installs a signal handler it will not know of the + * speculative nature of the 'live' registers and may infer the wrong + * thing. + */ + +#include +#include +#include +#include +#include + +#include + +#include "utils.h" +#include "tm.h" + +#define MAX_ATTEMPT 50 + +#define NV_VSX_REGS 12 + +long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss); + +static sig_atomic_t fail; + +vector int vss[] = { + {1, 2, 3, 4 },{5, 6, 7, 8 },{9, 10,11,12}, + {13,14,15,16},{17,18,19,20},{21,22,23,24}, + {25,26,27,28},{29,30,31,32},{33,34,35,36}, + {37,38,39,40},{41,42,43,44},{45,46,47,48}, + {-1, -2, -3, -4 },{-5, -6, -7, -8 },{-9, -10,-11,-12}, + {-13,-14,-15,-16},{-17,-18,-19,-20},{-21,-22,-23,-24}, + {-25,-26,-27,-28},{-29,-30,-31,-32},{-33,-34,-35,-36}, + {-37,-38,-39,-40},{-41,-42,-43,-44},{-45,-46,-47,-48} +}; + +static void signal_usr1(int signum, siginfo_t *info, void *uc) +{ + int i; + uint8_t vsc[sizeof(vector int)]; + uint8_t vst[sizeof(vector int)]; + ucontext_t *ucp = uc; + ucontext_t *tm_ucp = ucp->uc_link; + + /* +* The other half of the VSX regs will be after v_regs. +* +* In short, vmx_reserve array holds everything. v_regs is a 16 +* byte aligned pointer at the start of vmx_reserve (vmx_reserve +* may or may not be 16 aligned) where the v_regs structure exists. +* (half of) The VSX regsters are directly after v_regs so the +* easiest way to find them below. +*/ + long *vsx_ptr = (long *)(ucp->uc_mcontext.v_regs + 1); + long *tm_vsx_ptr = (long *)(tm_ucp->uc_mcontext.v_regs + 1); + for (i = 0; i < NV_VSX_REGS && !fail; i++) { + memcpy(vsc, >uc_mcontext.fp_regs[i + 20], 8); + memcpy(vsc + 8, _ptr[20 + i], 8); + fail = memcmp(vsc, [i], sizeof(vector int)); + memcpy(vst, _ucp->uc_mcontext.fp_regs[i + 20], 8); + memcpy(vst + 8, _vsx_ptr[20 + i], 8); + fail |= memcmp(vst, [i + NV_VSX_REGS], sizeof(vector int)); + + if (fail) { + int j; + + fprintf(stderr, "Failed on %d vsx 0x", i); + for (j = 0; j < 16; j++) + fprintf(stderr, "%02x", vsc[j]); + fprintf(stderr, " vs 0x"); + for (j = 0; j < 16; j++) + fprintf(stderr, "%02x", vst[j]); + fprintf(stderr, "\n"); + } + } +} + +static int tm_signal_context_chk() +{ + struct sigaction act; + int i; + long rc; + pid_t pid = getpid(); + +
[PATCH v5 13/20] selftests/powerpc: Check that signals always get delivered
Signed-off-by: Cyril Bur--- tools/testing/selftests/powerpc/Makefile | 1 + tools/testing/selftests/powerpc/signal/Makefile| 12 +++ tools/testing/selftests/powerpc/signal/signal.S| 50 ++ tools/testing/selftests/powerpc/signal/signal.c| 111 + tools/testing/selftests/powerpc/signal/signal_tm.c | 110 5 files changed, 284 insertions(+) create mode 100644 tools/testing/selftests/powerpc/signal/Makefile create mode 100644 tools/testing/selftests/powerpc/signal/signal.S create mode 100644 tools/testing/selftests/powerpc/signal/signal.c create mode 100644 tools/testing/selftests/powerpc/signal/signal_tm.c diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile index 1cc6d64..db54a33 100644 --- a/tools/testing/selftests/powerpc/Makefile +++ b/tools/testing/selftests/powerpc/Makefile @@ -19,6 +19,7 @@ SUB_DIRS = alignment \ dscr \ mm \ pmu \ + signal \ primitives \ stringloops \ switch_endian\ diff --git a/tools/testing/selftests/powerpc/signal/Makefile b/tools/testing/selftests/powerpc/signal/Makefile new file mode 100644 index 000..97944cf --- /dev/null +++ b/tools/testing/selftests/powerpc/signal/Makefile @@ -0,0 +1,12 @@ +TEST_PROGS := signal signal_tm + +all: $(TEST_PROGS) + +$(TEST_PROGS): ../harness.c ../utils.c signal.S + +signal_tm: CFLAGS += -mhtm + +include ../../lib.mk + +clean: + rm -f $(TEST_PROGS) *.o diff --git a/tools/testing/selftests/powerpc/signal/signal.S b/tools/testing/selftests/powerpc/signal/signal.S new file mode 100644 index 000..7043d52 --- /dev/null +++ b/tools/testing/selftests/powerpc/signal/signal.S @@ -0,0 +1,50 @@ +/* + * Copyright 2015, Cyril Bur, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include "../basic_asm.h" + +/* long signal_self(pid_t pid, int sig); */ +FUNC_START(signal_self) + li r0,37 /* sys_kill */ + /* r3 already has our pid in it */ + /* r4 already has signal type in it */ + sc + bc 4,3,1f + subfze r3,r3 +1: blr +FUNC_END(signal_self) + +/* long tm_signal_self(pid_t pid, int sig, int *ret); */ +FUNC_START(tm_signal_self) + PUSH_BASIC_STACK(8) + std r5,STACK_FRAME_PARAM(0)(sp) /* ret */ + tbegin. + beq 1f + tsuspend. + li r0,37 /* sys_kill */ + /* r3 already has our pid in it */ + /* r4 already has signal type in it */ + sc + ld r5,STACK_FRAME_PARAM(0)(sp) /* ret */ + bc 4,3,2f + subfze r3,r3 +2: std r3,0(r5) + tabort. 0 + tresume. /* Be nice to some cleanup, jumps back to tbegin then to 1: */ + /* +* Transaction should be proper doomed and we should never get +* here +*/ + li r3,1 + POP_BASIC_STACK(8) + blr +1: li r3,0 + POP_BASIC_STACK(8) + blr +FUNC_END(tm_signal_self) diff --git a/tools/testing/selftests/powerpc/signal/signal.c b/tools/testing/selftests/powerpc/signal/signal.c new file mode 100644 index 000..e7dedd2 --- /dev/null +++ b/tools/testing/selftests/powerpc/signal/signal.c @@ -0,0 +1,111 @@ +/* + * Copyright 2016, Cyril Bur, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Sending one self a signal should always get delivered. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "utils.h" + +#define MAX_ATTEMPT 50 +#define TIMEOUT 5 + +extern long signal_self(pid_t pid, int sig); + +static sig_atomic_t signaled; +static sig_atomic_t fail; + +static void signal_handler(int sig) +{ + if (sig == SIGUSR1) + signaled = 1; + else + fail = 1; +} + +static int test_signal() +{ + int i; + struct sigaction act; + pid_t ppid = getpid(); + pid_t pid; + + act.sa_handler = signal_handler; + act.sa_flags = 0; + sigemptyset(_mask); + if (sigaction(SIGUSR1, , NULL) < 0) { + perror("sigaction SIGUSR1"); + exit(1); + } + if (sigaction(SIGALRM, , NULL) < 0) { + perror("sigaction SIGALRM"); + exit(1); + } + + /* Don't do this for MAX_ATTEMPT, its simply too long */ + for(i = 0; i < 1000; i++) { +
[PATCH v5 12/20] selftests/powerpc: Add TM tcheck helpers in C
Signed-off-by: Cyril Bur--- tools/testing/selftests/powerpc/tm/tm.h | 27 +++ 1 file changed, 27 insertions(+) diff --git a/tools/testing/selftests/powerpc/tm/tm.h b/tools/testing/selftests/powerpc/tm/tm.h index 60318ba..2c8da74 100644 --- a/tools/testing/selftests/powerpc/tm/tm.h +++ b/tools/testing/selftests/powerpc/tm/tm.h @@ -52,4 +52,31 @@ static inline bool failure_is_nesting(void) return (__builtin_get_texasru() & 0x40); } +static inline int tcheck(void) +{ + long cr; + asm volatile ("tcheck 0" : "=r"(cr) : : "cr0"); + return (cr >> 28) & 4; +} + +static inline bool tcheck_doomed(void) +{ + return tcheck() & 8; +} + +static inline bool tcheck_active(void) +{ + return tcheck() & 4; +} + +static inline bool tcheck_suspended(void) +{ + return tcheck() & 2; +} + +static inline bool tcheck_transactional(void) +{ + return tcheck() & 6; +} + #endif /* _SELFTESTS_POWERPC_TM_TM_H */ -- 2.10.0
[PATCH v5 02/20] powerpc: Always restore FPU/VEC/VSX if hardware transactional memory in use
Comment from arch/powerpc/kernel/process.c:967: If userspace is inside a transaction (whether active or suspended) and FP/VMX/VSX instructions have ever been enabled inside that transaction, then we have to keep them enabled and keep the FP/VMX/VSX state loaded while ever the transaction continues. The reason is that if we didn't, and subsequently got a FP/VMX/VSX unavailable interrupt inside a transaction, we don't know whether it's the same transaction, and thus we don't know which of the checkpointed state and the ransactional state to use. restore_math() restore_fp() and restore_altivec() currently may not restore the registers. It doesn't appear that this is more serious than a performance penalty. If the math registers aren't restored the userspace thread will still be run with the facility disabled. Userspace will not be able to read invalid values. On the first access it will take an facility unavailable exception and the kernel will detected an active transaction, at which point it will abort the transaction. There is the possibility for a pathological case preventing any progress by transactions, however, transactions are never guaranteed to make progress. Fixes: 70fe3d9 ("powerpc: Restore FPU/VEC/VSX if previously used") Signed-off-by: Cyril Bur--- arch/powerpc/kernel/process.c | 21 ++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index ce8a26a..3846fab 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -89,7 +89,13 @@ static void check_if_tm_restore_required(struct task_struct *tsk) set_thread_flag(TIF_RESTORE_TM); } } + +static inline bool msr_tm_active(unsigned long msr) +{ + return MSR_TM_ACTIVE(msr); +} #else +static inline bool msr_tm_active(unsigned long msr) { return false; } static inline void check_if_tm_restore_required(struct task_struct *tsk) { } #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ @@ -209,7 +215,7 @@ void enable_kernel_fp(void) EXPORT_SYMBOL(enable_kernel_fp); static int restore_fp(struct task_struct *tsk) { - if (tsk->thread.load_fp) { + if (tsk->thread.load_fp || msr_tm_active(tsk->thread.regs->msr)) { load_fp_state(>thread.fp_state); current->thread.load_fp++; return 1; @@ -279,7 +285,8 @@ EXPORT_SYMBOL_GPL(flush_altivec_to_thread); static int restore_altivec(struct task_struct *tsk) { - if (cpu_has_feature(CPU_FTR_ALTIVEC) && tsk->thread.load_vec) { + if (cpu_has_feature(CPU_FTR_ALTIVEC) && + (tsk->thread.load_vec || msr_tm_active(tsk->thread.regs->msr))) { load_vr_state(>thread.vr_state); tsk->thread.used_vr = 1; tsk->thread.load_vec++; @@ -465,7 +472,8 @@ void restore_math(struct pt_regs *regs) { unsigned long msr; - if (!current->thread.load_fp && !loadvec(current->thread)) + if (!msr_tm_active(regs->msr) && + !current->thread.load_fp && !loadvec(current->thread)) return; msr = regs->msr; @@ -984,6 +992,13 @@ void restore_tm_state(struct pt_regs *regs) msr_diff = current->thread.ckpt_regs.msr & ~regs->msr; msr_diff &= MSR_FP | MSR_VEC | MSR_VSX; + /* Ensure that restore_math() will restore */ + if (msr_diff & MSR_FP) + current->thread.load_fp = 1; +#ifdef CONFIG_ALIVEC + if (cpu_has_feature(CPU_FTR_ALTIVEC) && msr_diff & MSR_VEC) + current->thread.load_vec = 1; +#endif restore_math(regs); regs->msr |= msr_diff; -- 2.10.0
[PATCH v5 01/20] selftests/powerpc: Compile selftests against headers without AT_HWCAP2
It might be nice to compile selftests against older kernels and headers but which may not have HWCAP2. Signed-off-by: Cyril Bur--- tools/testing/selftests/powerpc/utils.h | 7 +++ 1 file changed, 7 insertions(+) diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h index fbd33e5..ecd11b5 100644 --- a/tools/testing/selftests/powerpc/utils.h +++ b/tools/testing/selftests/powerpc/utils.h @@ -32,10 +32,17 @@ static inline bool have_hwcap(unsigned long ftr) return ((unsigned long)get_auxv_entry(AT_HWCAP) & ftr) == ftr; } +#ifdef AT_HWCAP2 static inline bool have_hwcap2(unsigned long ftr2) { return ((unsigned long)get_auxv_entry(AT_HWCAP2) & ftr2) == ftr2; } +#else +static inline bool have_hwcap2(unsigned long ftr2) +{ + return false; +} +#endif /* Yes, this is evil */ #define FAIL_IF(x) \ -- 2.10.0
[PATCH v5 03/20] powerpc: Add check_if_tm_restore_required() to giveup_all()
giveup_all() causes FPU/VMX/VSX facilities to be disabled in a threads MSR. If the thread performing the giveup was transactional, the kernel must record which facilities were in use before the giveup as the thread must have these facilities re-enabled on return to userspace. >From process.c: /* * This is called if we are on the way out to userspace and the * TIF_RESTORE_TM flag is set. It checks if we need to reload * FP and/or vector state and does so if necessary. * If userspace is inside a transaction (whether active or * suspended) and FP/VMX/VSX instructions have ever been enabled * inside that transaction, then we have to keep them enabled * and keep the FP/VMX/VSX state loaded while ever the transaction * continues. The reason is that if we didn't, and subsequently * got a FP/VMX/VSX unavailable interrupt inside a transaction, * we don't know whether it's the same transaction, and thus we * don't know which of the checkpointed state and the transactional * state to use. */ Calling check_if_tm_restore_required() will set TIF_RESTORE_TM and save the MSR if needed. Fixes: c208505 ("powerpc: create giveup_all()") Signed-off-by: Cyril Bur--- arch/powerpc/kernel/process.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 3846fab..5029567 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -446,6 +446,7 @@ void giveup_all(struct task_struct *tsk) return; msr_check_and_set(msr_all_available); + check_if_tm_restore_required(tsk); #ifdef CONFIG_PPC_FPU if (usermsr & MSR_FP) -- 2.10.0
[PATCH v5 10/20] selftests/powerpc: Introduce GPR asm helper header file
Signed-off-by: Cyril Bur--- tools/testing/selftests/powerpc/gpr_asm.h | 96 +++ 1 file changed, 96 insertions(+) create mode 100644 tools/testing/selftests/powerpc/gpr_asm.h diff --git a/tools/testing/selftests/powerpc/gpr_asm.h b/tools/testing/selftests/powerpc/gpr_asm.h new file mode 100644 index 000..f6f3885 --- /dev/null +++ b/tools/testing/selftests/powerpc/gpr_asm.h @@ -0,0 +1,96 @@ +/* + * Copyright 2016, Cyril Bur, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _SELFTESTS_POWERPC_GPR_ASM_H +#define _SELFTESTS_POWERPC_GPR_ASM_H + +#include "basic_asm.h" + +#define __PUSH_NVREGS(top_pos); \ + std r31,(top_pos)(%r1); \ + std r30,(top_pos - 8)(%r1); \ + std r29,(top_pos - 16)(%r1); \ + std r28,(top_pos - 24)(%r1); \ + std r27,(top_pos - 32)(%r1); \ + std r26,(top_pos - 40)(%r1); \ + std r25,(top_pos - 48)(%r1); \ + std r24,(top_pos - 56)(%r1); \ + std r23,(top_pos - 64)(%r1); \ + std r22,(top_pos - 72)(%r1); \ + std r21,(top_pos - 80)(%r1); \ + std r20,(top_pos - 88)(%r1); \ + std r19,(top_pos - 96)(%r1); \ + std r18,(top_pos - 104)(%r1); \ + std r17,(top_pos - 112)(%r1); \ + std r16,(top_pos - 120)(%r1); \ + std r15,(top_pos - 128)(%r1); \ + std r14,(top_pos - 136)(%r1) + +#define __POP_NVREGS(top_pos); \ + ld r31,(top_pos)(%r1); \ + ld r30,(top_pos - 8)(%r1); \ + ld r29,(top_pos - 16)(%r1); \ + ld r28,(top_pos - 24)(%r1); \ + ld r27,(top_pos - 32)(%r1); \ + ld r26,(top_pos - 40)(%r1); \ + ld r25,(top_pos - 48)(%r1); \ + ld r24,(top_pos - 56)(%r1); \ + ld r23,(top_pos - 64)(%r1); \ + ld r22,(top_pos - 72)(%r1); \ + ld r21,(top_pos - 80)(%r1); \ + ld r20,(top_pos - 88)(%r1); \ + ld r19,(top_pos - 96)(%r1); \ + ld r18,(top_pos - 104)(%r1); \ + ld r17,(top_pos - 112)(%r1); \ + ld r16,(top_pos - 120)(%r1); \ + ld r15,(top_pos - 128)(%r1); \ + ld r14,(top_pos - 136)(%r1) + +#define PUSH_NVREGS(stack_size) \ + __PUSH_NVREGS(stack_size + STACK_FRAME_MIN_SIZE) + +/* 18 NV FPU REGS */ +#define PUSH_NVREGS_BELOW_FPU(stack_size) \ + __PUSH_NVREGS(stack_size + STACK_FRAME_MIN_SIZE - (18 * 8)) + +#define POP_NVREGS(stack_size) \ + __POP_NVREGS(stack_size + STACK_FRAME_MIN_SIZE) + +/* 18 NV FPU REGS */ +#define POP_NVREGS_BELOW_FPU(stack_size) \ + __POP_NVREGS(stack_size + STACK_FRAME_MIN_SIZE - (18 * 8)) + +/* + * Careful calling this, it will 'clobber' NVGPRs (by design) + * Don't call this from C + */ +FUNC_START(load_gpr) + ld r14,0(r3) + ld r15,8(r3) + ld r16,16(r3) + ld r17,24(r3) + ld r18,32(r3) + ld r19,40(r3) + ld r20,48(r3) + ld r21,56(r3) + ld r22,64(r3) + ld r23,72(r3) + ld r24,80(r3) + ld r25,88(r3) + ld r26,96(r3) + ld r27,104(r3) + ld r28,112(r3) + ld r29,120(r3) + ld r30,128(r3) + ld r31,136(r3) + blr +FUNC_END(load_gpr) + + +#endif /* _SELFTESTS_POWERPC_GPR_ASM_H */ -- 2.10.0
[PATCH v5 06/20] powerpc: signals: Stop using current in signal code
Much of the signal code takes a pt_regs on which it operates. Over time the signal code has needed to know more about the thread than what pt_regs can supply, this information is obtained as needed by using 'current'. This approach is not strictly incorrect however it does mean that there is now a hard requirement that the pt_regs being passed around does belong to current, this is never checked. A safer approach is for the majority of the signal functions to take a task_struct from which they can obtain pt_regs and any other information they need. The caveat that the task_struct they are passed must be current doesn't go away but can more easily be checked for. Functions called from outside powerpc signal code are passed a pt_regs and they can confirm that the pt_regs is that of current and pass current to other functions, furthurmore, powerpc signal functions can check that the task_struct they are passed is the same as current avoiding possible corruption of current (or the task they are passed) if this assertion ever fails. CC: pau...@samba.org Signed-off-by: Cyril Bur--- arch/powerpc/include/asm/signal.h | 2 - arch/powerpc/kernel/signal.c | 41 arch/powerpc/kernel/signal.h | 10 +- arch/powerpc/kernel/signal_32.c | 31 +++--- arch/powerpc/kernel/signal_64.c | 201 +- 5 files changed, 159 insertions(+), 126 deletions(-) diff --git a/arch/powerpc/include/asm/signal.h b/arch/powerpc/include/asm/signal.h index 9322c28..5ff7772 100644 --- a/arch/powerpc/include/asm/signal.h +++ b/arch/powerpc/include/asm/signal.h @@ -5,6 +5,4 @@ #include #include -extern unsigned long get_tm_stackpointer(struct pt_regs *regs); - #endif /* _ASM_POWERPC_SIGNAL_H */ diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index cb64d6f..bbe77ae 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c @@ -99,22 +99,24 @@ static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, } } -static void do_signal(struct pt_regs *regs) +static void do_signal(struct task_struct *tsk) { sigset_t *oldset = sigmask_to_save(); struct ksignal ksig; int ret; int is32 = is_32bit_task(); + BUG_ON(tsk != current); + get_signal(); /* Is there any syscall restart business here ? */ - check_syscall_restart(regs, , ksig.sig > 0); + check_syscall_restart(tsk->thread.regs, , ksig.sig > 0); if (ksig.sig <= 0) { /* No signal to deliver -- put the saved sigmask back */ restore_saved_sigmask(); - regs->trap = 0; + tsk->thread.regs->trap = 0; return; /* no signals delivered */ } @@ -124,23 +126,22 @@ static void do_signal(struct pt_regs *regs) * user space. The DABR will have been cleared if it * triggered inside the kernel. */ - if (current->thread.hw_brk.address && - current->thread.hw_brk.type) - __set_breakpoint(>thread.hw_brk); + if (tsk->thread.hw_brk.address && tsk->thread.hw_brk.type) + __set_breakpoint(>thread.hw_brk); #endif /* Re-enable the breakpoints for the signal stack */ - thread_change_pc(current, regs); + thread_change_pc(tsk, tsk->thread.regs); if (is32) { if (ksig.ka.sa.sa_flags & SA_SIGINFO) - ret = handle_rt_signal32(, oldset, regs); + ret = handle_rt_signal32(, oldset, tsk); else - ret = handle_signal32(, oldset, regs); + ret = handle_signal32(, oldset, tsk); } else { - ret = handle_rt_signal64(, oldset, regs); + ret = handle_rt_signal64(, oldset, tsk); } - regs->trap = 0; + tsk->thread.regs->trap = 0; signal_setup_done(ret, , test_thread_flag(TIF_SINGLESTEP)); } @@ -151,8 +152,10 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) if (thread_info_flags & _TIF_UPROBE) uprobe_notify_resume(regs); - if (thread_info_flags & _TIF_SIGPENDING) - do_signal(regs); + if (thread_info_flags & _TIF_SIGPENDING) { + BUG_ON(regs != current->thread.regs); + do_signal(current); + } if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); @@ -162,7 +165,7 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) user_enter(); } -unsigned long get_tm_stackpointer(struct pt_regs *regs) +unsigned long get_tm_stackpointer(struct task_struct *tsk) { /* When in an active transaction that takes a signal, we need to be * careful with the stack. It's possible that the stack has moved back @@ -187,11
[PATCH v5 04/20] powerpc: Return the new MSR from msr_check_and_set()
msr_check_and_set() always performs a mfmsr() to determine if it needs to perform an mtmsr(), as mfmsr() can be a costly operation msr_check_and_set() could return the MSR now on the CPU to avoid callers of msr_check_and_set having to make their own mfmsr() call. Signed-off-by: Cyril Bur--- arch/powerpc/include/asm/reg.h | 2 +- arch/powerpc/kernel/process.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 9dddabc..a8f63bc 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -1250,7 +1250,7 @@ static inline void mtmsr_isync(unsigned long val) : "memory") #endif -extern void msr_check_and_set(unsigned long bits); +extern unsigned long msr_check_and_set(unsigned long bits); extern bool strict_msr_control; extern void __msr_check_and_clear(unsigned long bits); static inline void msr_check_and_clear(unsigned long bits) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 5029567..34ee5f2 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -111,7 +111,7 @@ static int __init enable_strict_msr_control(char *str) } early_param("ppc_strict_facility_enable", enable_strict_msr_control); -void msr_check_and_set(unsigned long bits) +unsigned long msr_check_and_set(unsigned long bits) { unsigned long oldmsr = mfmsr(); unsigned long newmsr; @@ -125,6 +125,8 @@ void msr_check_and_set(unsigned long bits) if (oldmsr != newmsr) mtmsr_isync(newmsr); + + return newmsr; } void __msr_check_and_clear(unsigned long bits) -- 2.10.0
[PATCH v5 00/20] Consistent TM structures
v5: Rebased on powerpc-next to solve conflict with commit e1c0d66fcb179a1737b3d5cc11c6e37bcabbd861 Author: Simon GuoDate: Tue Jul 26 16:06:01 2016 +0800 powerpc: Set used_(vsr|vr|spe) in sigreturn path when MSR bits are active v4: Address review from Mikey, comment and commit message changes. Dropped patch "selftests/powerpc: Add TM tcheck helpers in C" as it was unused. V3: In v2 the MSR_{FP,VEC,VSX} bits were left on (if in use) after a reclaim which meant that signal code did the correct thing. This also meant that the bits would stay on when a (transactional) thread was not running and ptrace flush code would notice that tasks not current have MSR_{FP,VEC,VSX} set when attempting to flush, this is incorrect. The correct solution was to have the signal code make decisions about the use of FP,VEC or VSX by observing the checkpointed MSR and not the regs->msr. This meant adding another reference to current in signal code which was getting messy. Patch "powerpc: signals: Stop using current in signal code" addresses this and allows for a cleaner fix. Fix build issues for 32bit. V2 Coverletter: This series has grown considerably from v1. Similarities with v1 include: - Selftests are all the same, they have simply been split into several patches with comments from MPE and Daniel Axtens incorporated. It is possible some things slipped through the cracks selftest wise as the focus has been on the final three patches. - The final three patches have been reworked following extra testing and from review by Simon Guo. Differences include: - Patches 2-5 are fixes for existing problems found in the course of verifying the final three patches. In the case of "powerpc: Never giveup a reclaimed thread when enabling kernel {fp, altivec, vsx}" it has proven difficult to narrow down when the bug was introduced. It does not exist in 3.8 when TM was introduced but does exist in 4.4. I was unable to boot 3.13 (or 3.12) in an attempt to further bisect. - As ptrace code was merged between v1 and v2, work was needed there to make it fit in with the final three patches. The overall aim of this series may have gotten lost here. The final three patches are the goal here. Cyril Bur (20): selftests/powerpc: Compile selftests against headers without AT_HWCAP2 powerpc: Always restore FPU/VEC/VSX if hardware transactional memory in use powerpc: Add check_if_tm_restore_required() to giveup_all() powerpc: Return the new MSR from msr_check_and_set() powerpc: Never giveup a reclaimed thread when enabling kernel {fp, altivec, vsx} powerpc: signals: Stop using current in signal code selftests/powerpc: Check for VSX preservation across userspace preemption selftests/powerpc: Rework FPU stack placement macros and move to header file selftests/powerpc: Move VMX stack frame macros to header file selftests/powerpc: Introduce GPR asm helper header file selftests/powerpc: Allow tests to extend their kill timeout selftests/powerpc: Add TM tcheck helpers in C selftests/powerpc: Check that signals always get delivered selftests/powerpc: Add checks for transactional GPRs in signal contexts selftests/powerpc: Add checks for transactional FPUs in signal contexts selftests/powerpc: Add checks for transactional VMXs in signal contexts selftests/powerpc: Add checks for transactional VSXs in signal contexts powerpc: tm: Always use fp_state and vr_state to store live registers powerpc: tm: Rename transct_(*) to ck(\1)_state powerpc: Remove do_load_up_transact_{fpu,altivec} arch/powerpc/include/asm/processor.h | 15 +- arch/powerpc/include/asm/reg.h | 2 +- arch/powerpc/include/asm/signal.h | 2 - arch/powerpc/include/asm/tm.h | 5 - arch/powerpc/kernel/asm-offsets.c | 12 +- arch/powerpc/kernel/fpu.S | 26 -- arch/powerpc/kernel/process.c | 152 +-- arch/powerpc/kernel/ptrace.c | 278 + arch/powerpc/kernel/signal.c | 41 +-- arch/powerpc/kernel/signal.h | 18 +- arch/powerpc/kernel/signal_32.c| 115 - arch/powerpc/kernel/signal_64.c| 203 --- arch/powerpc/kernel/tm.S | 94 +++ arch/powerpc/kernel/traps.c| 12 +- arch/powerpc/kernel/vector.S | 25 -- tools/testing/selftests/powerpc/Makefile | 1 + tools/testing/selftests/powerpc/fpu_asm.h | 81 ++ tools/testing/selftests/powerpc/gpr_asm.h | 96 +++ tools/testing/selftests/powerpc/harness.c | 9 +- tools/testing/selftests/powerpc/math/Makefile | 4 +- tools/testing/selftests/powerpc/math/fpu_asm.S | 73 +-
[PATCH v5 20/20] powerpc: Remove do_load_up_transact_{fpu,altivec}
Previous rework of TM code leaves these functions unused Signed-off-by: Cyril Bur--- arch/powerpc/include/asm/tm.h | 5 - arch/powerpc/kernel/fpu.S | 26 -- arch/powerpc/kernel/vector.S | 25 - 3 files changed, 56 deletions(-) diff --git a/arch/powerpc/include/asm/tm.h b/arch/powerpc/include/asm/tm.h index c22d704..82e06ca 100644 --- a/arch/powerpc/include/asm/tm.h +++ b/arch/powerpc/include/asm/tm.h @@ -9,11 +9,6 @@ #ifndef __ASSEMBLY__ -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM -extern void do_load_up_transact_fpu(struct thread_struct *thread); -extern void do_load_up_transact_altivec(struct thread_struct *thread); -#endif - extern void tm_enable(void); extern void tm_reclaim(struct thread_struct *thread, unsigned long orig_msr, uint8_t cause); diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index 181c187..08d14b0 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S @@ -50,32 +50,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ #define REST_32FPVSRS(n,c,base) __REST_32FPVSRS(n,__REG_##c,__REG_##base) #define SAVE_32FPVSRS(n,c,base) __SAVE_32FPVSRS(n,__REG_##c,__REG_##base) -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM -/* void do_load_up_transact_fpu(struct thread_struct *thread) - * - * This is similar to load_up_fpu but for the transactional version of the FP - * register set. It doesn't mess with the task MSR or valid flags. - * Furthermore, we don't do lazy FP with TM currently. - */ -_GLOBAL(do_load_up_transact_fpu) - mfmsr r6 - ori r5,r6,MSR_FP -#ifdef CONFIG_VSX -BEGIN_FTR_SECTION - orisr5,r5,MSR_VSX@h -END_FTR_SECTION_IFSET(CPU_FTR_VSX) -#endif - SYNC - MTMSRD(r5) - - addir7,r3,THREAD_CKFPSTATE - lfd fr0,FPSTATE_FPSCR(r7) - MTFSF_L(fr0) - REST_32FPVSRS(0, R4, R7) - - blr -#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ - /* * Load state from memory into FP registers including FPSCR. * Assumes the caller has enabled FP in the MSR. diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S index 7dc4021..bc85bdf 100644 --- a/arch/powerpc/kernel/vector.S +++ b/arch/powerpc/kernel/vector.S @@ -7,31 +7,6 @@ #include #include -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM -/* void do_load_up_transact_altivec(struct thread_struct *thread) - * - * This is similar to load_up_altivec but for the transactional version of the - * vector regs. It doesn't mess with the task MSR or valid flags. - * Furthermore, VEC laziness is not supported with TM currently. - */ -_GLOBAL(do_load_up_transact_altivec) - mfmsr r6 - orisr5,r6,MSR_VEC@h - MTMSRD(r5) - isync - - li r4,1 - stw r4,THREAD_USED_VR(r3) - - li r10,THREAD_CKVRSTATE+VRSTATE_VSCR - lvx v0,r10,r3 - mtvscr v0 - addir10,r3,THREAD_CKVRSTATE - REST_32VRS(0,r4,r10) - - blr -#endif - /* * Load state from memory into VMX registers including VSCR. * Assumes the caller has enabled VMX in the MSR. -- 2.10.0
[PATCH v5 11/20] selftests/powerpc: Allow tests to extend their kill timeout
Signed-off-by: Cyril Bur--- tools/testing/selftests/powerpc/harness.c | 9 +++-- tools/testing/selftests/powerpc/utils.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/powerpc/harness.c b/tools/testing/selftests/powerpc/harness.c index 52f9be7..248a820 100644 --- a/tools/testing/selftests/powerpc/harness.c +++ b/tools/testing/selftests/powerpc/harness.c @@ -19,9 +19,9 @@ #include "subunit.h" #include "utils.h" -#define TIMEOUT120 #define KILL_TIMEOUT 5 +static uint64_t timeout = 120; int run_test(int (test_function)(void), char *name) { @@ -44,7 +44,7 @@ int run_test(int (test_function)(void), char *name) setpgid(pid, pid); /* Wake us up in timeout seconds */ - alarm(TIMEOUT); + alarm(timeout); terminated = false; wait: @@ -94,6 +94,11 @@ static struct sigaction alarm_action = { .sa_handler = alarm_handler, }; +void test_harness_set_timeout(uint64_t time) +{ + timeout = time; +} + int test_harness(int (test_function)(void), char *name) { int rc; diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h index ecd11b5..53405e8 100644 --- a/tools/testing/selftests/powerpc/utils.h +++ b/tools/testing/selftests/powerpc/utils.h @@ -22,7 +22,7 @@ typedef uint32_t u32; typedef uint16_t u16; typedef uint8_t u8; - +void test_harness_set_timeout(uint64_t time); int test_harness(int (test_function)(void), char *name); extern void *get_auxv_entry(int type); int pick_online_cpu(void); -- 2.10.0
[PATCH v5 19/20] powerpc: tm: Rename transct_(*) to ck(\1)_state
Make the structures being used for checkpointed state named consistently with the pt_regs/ckpt_regs. Signed-off-by: Cyril Bur--- arch/powerpc/include/asm/processor.h | 8 ++--- arch/powerpc/kernel/asm-offsets.c| 12 arch/powerpc/kernel/fpu.S| 2 +- arch/powerpc/kernel/process.c| 4 +-- arch/powerpc/kernel/ptrace.c | 46 +-- arch/powerpc/kernel/signal.h | 8 ++--- arch/powerpc/kernel/signal_32.c | 60 ++-- arch/powerpc/kernel/signal_64.c | 32 +-- arch/powerpc/kernel/tm.S | 12 arch/powerpc/kernel/vector.S | 4 +-- 10 files changed, 94 insertions(+), 94 deletions(-) diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index feab2ce..b3e0cfc 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -147,7 +147,7 @@ typedef struct { } mm_segment_t; #define TS_FPR(i) fp_state.fpr[i][TS_FPROFFSET] -#define TS_TRANS_FPR(i) transact_fp.fpr[i][TS_FPROFFSET] +#define TS_CKFPR(i) ckfp_state.fpr[i][TS_FPROFFSET] /* FP and VSX 0-31 register set */ struct thread_fp_state { @@ -275,9 +275,9 @@ struct thread_struct { * * These are analogous to how ckpt_regs and pt_regs work */ - struct thread_fp_state transact_fp; - struct thread_vr_state transact_vr; - unsigned long transact_vrsave; + struct thread_fp_state ckfp_state; /* Checkpointed FP state */ + struct thread_vr_state ckvr_state; /* Checkpointed VR state */ + unsigned long ckvrsave; /* Checkpointed VRSAVE */ #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ #ifdef CONFIG_KVM_BOOK3S_32_HANDLER void* kvm_shadow_vcpu; /* KVM internal data */ diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index b89d14c..dd0fc33 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -142,12 +142,12 @@ int main(void) DEFINE(THREAD_TM_PPR, offsetof(struct thread_struct, tm_ppr)); DEFINE(THREAD_TM_DSCR, offsetof(struct thread_struct, tm_dscr)); DEFINE(PT_CKPT_REGS, offsetof(struct thread_struct, ckpt_regs)); - DEFINE(THREAD_TRANSACT_VRSTATE, offsetof(struct thread_struct, -transact_vr)); - DEFINE(THREAD_TRANSACT_VRSAVE, offsetof(struct thread_struct, - transact_vrsave)); - DEFINE(THREAD_TRANSACT_FPSTATE, offsetof(struct thread_struct, -transact_fp)); + DEFINE(THREAD_CKVRSTATE, offsetof(struct thread_struct, +ckvr_state)); + DEFINE(THREAD_CKVRSAVE, offsetof(struct thread_struct, + ckvrsave)); + DEFINE(THREAD_CKFPSTATE, offsetof(struct thread_struct, +ckfp_state)); /* Local pt_regs on stack for Transactional Memory funcs. */ DEFINE(TM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index 15da2b5..181c187 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S @@ -68,7 +68,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) SYNC MTMSRD(r5) - addir7,r3,THREAD_TRANSACT_FPSTATE + addir7,r3,THREAD_CKFPSTATE lfd fr0,FPSTATE_FPSCR(r7) MTFSF_L(fr0) REST_32FPVSRS(0, R4, R7) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 6e9a054..e220330 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -851,8 +851,8 @@ static inline void tm_reclaim_task(struct task_struct *tsk) * * In switching we need to maintain a 2nd register state as * oldtask->thread.ckpt_regs. We tm_reclaim(oldproc); this saves the -* checkpointed (tbegin) state in ckpt_regs and saves the transactional -* (current) FPRs into oldtask->thread.transact_fpr[]. +* checkpointed (tbegin) state in ckpt_regs, ckfp_state and +* ckvr_state * * We also context switch (save) TFHAR/TEXASR/TFIAR in here. */ diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 7ae744f..b1ec62f 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -404,7 +404,7 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset, /* * Regardless of transactions, 'fp_state' holds the current running - * value of all FPR registers and 'transact_fp' holds the last checkpointed + * value of all FPR registers and 'ckfp_state' holds the last checkpointed * value of all FPR registers for the current transaction. * * Userspace
[PATCH v5 18/20] powerpc: tm: Always use fp_state and vr_state to store live registers
There is currently an inconsistency as to how the entire CPU register state is saved and restored when a thread uses transactional memory (TM). Using transactional memory results in the CPU having duplicated (almost) all of its register state. This duplication results in a set of registers which can be considered 'live', those being currently modified by the instructions being executed and another set that is frozen at a point in time. On context switch, both sets of state have to be saved and (later) restored. These two states are often called a variety of different things. Common terms for the state which only exists after the CPU has entered a transaction (performed a TBEGIN instruction) in hardware are 'transactional' or 'speculative'. Between a TBEGIN and a TEND or TABORT (or an event that causes the hardware to abort), regardless of the use of TSUSPEND the transactional state can be referred to as the live state. The second state is often to referred to as the 'checkpointed' state and is a duplication of the live state when the TBEGIN instruction is executed. This state is kept in the hardware and will be rolled back to on transaction failure. Currently all the registers stored in pt_regs are ALWAYS the live registers, that is, when a thread has transactional registers their values are stored in pt_regs and the checkpointed state is in ckpt_regs. A strange opposite is true for fp_state/vr_state. When a thread is non transactional fp_state/vr_state holds the live registers. When a thread has initiated a transaction fp_state/vr_state holds the checkpointed state and transact_fp/transact_vr become the structure which holds the live state (at this point it is a transactional state). This method creates confusion as to where the live state is, in some circumstances it requires extra work to determine where to put the live state and prevents the use of common functions designed (probably before TM) to save the live state. With this patch pt_regs, fp_state and vr_state all represent the same thing and the other structures [pending rename] are for checkpointed state. Acked-by: Simon GuoSigned-off-by: Cyril Bur --- arch/powerpc/include/asm/processor.h | 7 +- arch/powerpc/kernel/process.c| 83 +++ arch/powerpc/kernel/ptrace.c | 278 +-- arch/powerpc/kernel/signal_32.c | 50 +++ arch/powerpc/kernel/signal_64.c | 54 +++ arch/powerpc/kernel/tm.S | 94 ++-- arch/powerpc/kernel/traps.c | 12 +- 7 files changed, 197 insertions(+), 381 deletions(-) diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 68e3bf5..feab2ce 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -267,16 +267,13 @@ struct thread_struct { unsigned long tm_dscr; /* -* Transactional FP and VSX 0-31 register set. -* NOTE: the sense of these is the opposite of the integer ckpt_regs! +* Checkpointed FP and VSX 0-31 register set. * * When a transaction is active/signalled/scheduled etc., *regs is the * most recent set of/speculated GPRs with ckpt_regs being the older * checkpointed regs to which we roll back if transaction aborts. * -* However, fpr[] is the checkpointed 'base state' of FP regs, and -* transact_fpr[] is the new set of transactional values. -* VRs work the same way. +* These are analogous to how ckpt_regs and pt_regs work */ struct thread_fp_state transact_fp; struct thread_vr_state transact_vr; diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 45b6ea0..6e9a054 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -815,26 +815,6 @@ static inline bool hw_brk_match(struct arch_hw_breakpoint *a, static void tm_reclaim_thread(struct thread_struct *thr, struct thread_info *ti, uint8_t cause) { - unsigned long msr_diff = 0; - - /* -* If FP/VSX registers have been already saved to the -* thread_struct, move them to the transact_fp array. -* We clear the TIF_RESTORE_TM bit since after the reclaim -* the thread will no longer be transactional. -*/ - if (test_ti_thread_flag(ti, TIF_RESTORE_TM)) { - msr_diff = thr->ckpt_regs.msr & ~thr->regs->msr; - if (msr_diff & MSR_FP) - memcpy(>transact_fp, >fp_state, - sizeof(struct thread_fp_state)); - if (msr_diff & MSR_VEC) - memcpy(>transact_vr, >vr_state, - sizeof(struct thread_vr_state)); - clear_ti_thread_flag(ti, TIF_RESTORE_TM); - msr_diff &= MSR_FP | MSR_VEC | MSR_VSX | MSR_FE0 | MSR_FE1;
[PATCH v5 14/20] selftests/powerpc: Add checks for transactional GPRs in signal contexts
If a thread receives a signal while transactional the kernel creates a second context to show the transactional state of the process. This test loads some known values and waits for a signal and confirms that the expected values are in the signal context. Signed-off-by: Cyril Bur--- tools/testing/selftests/powerpc/tm/Makefile| 7 +- .../powerpc/tm/tm-signal-context-chk-gpr.c | 90 tools/testing/selftests/powerpc/tm/tm-signal.S | 114 + 3 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c create mode 100644 tools/testing/selftests/powerpc/tm/tm-signal.S diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile index 9d301d7..2b6fe8f 100644 --- a/tools/testing/selftests/powerpc/tm/Makefile +++ b/tools/testing/selftests/powerpc/tm/Makefile @@ -1,5 +1,7 @@ +SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr + TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \ - tm-vmxcopy tm-fork tm-tar tm-tmspr tm-exec tm-execed + tm-vmxcopy tm-fork tm-tar tm-tmspr $(SIGNAL_CONTEXT_CHK_TESTS) all: $(TEST_PROGS) @@ -11,6 +13,9 @@ tm-syscall: tm-syscall-asm.S tm-syscall: CFLAGS += -I../../../../../usr/include tm-tmspr: CFLAGS += -pthread +$(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S +$(SIGNAL_CONTEXT_CHK_TESTS): CFLAGS += -mhtm -m64 + include ../../lib.mk clean: diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c new file mode 100644 index 000..df91330 --- /dev/null +++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c @@ -0,0 +1,90 @@ +/* + * Copyright 2016, Cyril Bur, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * + * Test the kernel's signal frame code. + * + * The kernel sets up two sets of ucontexts if the signal was to be + * delivered while the thread was in a transaction. + * Expected behaviour is that the checkpointed state is in the user + * context passed to the signal handler. The speculated state can be + * accessed with the uc_link pointer. + * + * The rationale for this is that if TM unaware code (which linked + * against TM libs) installs a signal handler it will not know of the + * speculative nature of the 'live' registers and may infer the wrong + * thing. + */ + +#include +#include +#include +#include + +#include + +#include "utils.h" +#include "tm.h" + +#define MAX_ATTEMPT 50 + +#define NV_GPR_REGS 18 + +long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss); + +static sig_atomic_t fail; + +static long gps[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18}; + +static void signal_usr1(int signum, siginfo_t *info, void *uc) +{ + int i; + ucontext_t *ucp = uc; + ucontext_t *tm_ucp = ucp->uc_link; + + for (i = 0; i < NV_GPR_REGS && !fail; i++) { + fail = (ucp->uc_mcontext.gp_regs[i + 14] != gps[i]); + fail |= (tm_ucp->uc_mcontext.gp_regs[i + 14] != gps[i + NV_GPR_REGS]); + if (fail) + printf("Failed on %d GPR %lu or %lu\n", i, + ucp->uc_mcontext.gp_regs[i + 14], tm_ucp->uc_mcontext.gp_regs[i + 14]); + } +} + +static int tm_signal_context_chk_gpr() +{ + struct sigaction act; + int i; + long rc; + pid_t pid = getpid(); + + SKIP_IF(!have_htm()); + + act.sa_sigaction = signal_usr1; + sigemptyset(_mask); + act.sa_flags = SA_SIGINFO; + if (sigaction(SIGUSR1, , NULL) < 0) { + perror("sigaction sigusr1"); + exit(1); + } + + i = 0; + while (i < MAX_ATTEMPT && !fail) { + rc = tm_signal_self_context_load(pid, gps, NULL, NULL, NULL); + FAIL_IF(rc != pid); + i++; + } + + return fail; +} + +int main(void) +{ + return test_harness(tm_signal_context_chk_gpr, "tm_signal_context_chk_gpr"); +} diff --git a/tools/testing/selftests/powerpc/tm/tm-signal.S b/tools/testing/selftests/powerpc/tm/tm-signal.S new file mode 100644 index 000..4e13e8b --- /dev/null +++ b/tools/testing/selftests/powerpc/tm/tm-signal.S @@ -0,0 +1,114 @@ +/* + * Copyright 2015, Cyril Bur, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version
[PATCH v5 05/20] powerpc: Never giveup a reclaimed thread when enabling kernel {fp, altivec, vsx}
After a thread is reclaimed from its active or suspended transactional state the checkpointed state exists on CPU, this state (along with the live/transactional state) has been saved in its entirety by the reclaiming process. There exists a sequence of events that would cause the kernel to call one of enable_kernel_fp(), enable_kernel_altivec() or enable_kernel_vsx() after a thread has been reclaimed. These functions save away any user state on the CPU so that the kernel can use the registers. Not only is this saving away unnecessary at this point, it is actually incorrect. It causes a save of the checkpointed state to the live structures within the thread struct thus destroying the true live state for that thread. Signed-off-by: Cyril Bur--- arch/powerpc/kernel/process.c | 39 --- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 34ee5f2..45b6ea0 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -205,12 +205,23 @@ EXPORT_SYMBOL_GPL(flush_fp_to_thread); void enable_kernel_fp(void) { + unsigned long cpumsr; + WARN_ON(preemptible()); - msr_check_and_set(MSR_FP); + cpumsr = msr_check_and_set(MSR_FP); if (current->thread.regs && (current->thread.regs->msr & MSR_FP)) { check_if_tm_restore_required(current); + /* +* If a thread has already been reclaimed then the +* checkpointed registers are on the CPU but have definitely +* been saved by the reclaim code. Don't need to and *cannot* +* giveup as this would save to the 'live' structure not the +* checkpointed structure. +*/ + if(!msr_tm_active(cpumsr) && msr_tm_active(current->thread.regs->msr)) + return; __giveup_fpu(current); } } @@ -257,12 +268,23 @@ EXPORT_SYMBOL(giveup_altivec); void enable_kernel_altivec(void) { + unsigned long cpumsr; + WARN_ON(preemptible()); - msr_check_and_set(MSR_VEC); + cpumsr = msr_check_and_set(MSR_VEC); if (current->thread.regs && (current->thread.regs->msr & MSR_VEC)) { check_if_tm_restore_required(current); + /* +* If a thread has already been reclaimed then the +* checkpointed registers are on the CPU but have definitely +* been saved by the reclaim code. Don't need to and *cannot* +* giveup as this would save to the 'live' structure not the +* checkpointed structure. +*/ + if(!msr_tm_active(cpumsr) && msr_tm_active(current->thread.regs->msr)) + return; __giveup_altivec(current); } } @@ -331,12 +353,23 @@ static void save_vsx(struct task_struct *tsk) void enable_kernel_vsx(void) { + unsigned long cpumsr; + WARN_ON(preemptible()); - msr_check_and_set(MSR_FP|MSR_VEC|MSR_VSX); + cpumsr = msr_check_and_set(MSR_FP|MSR_VEC|MSR_VSX); if (current->thread.regs && (current->thread.regs->msr & MSR_VSX)) { check_if_tm_restore_required(current); + /* +* If a thread has already been reclaimed then the +* checkpointed registers are on the CPU but have definitely +* been saved by the reclaim code. Don't need to and *cannot* +* giveup as this would save to the 'live' structure not the +* checkpointed structure. +*/ + if(!msr_tm_active(cpumsr) && msr_tm_active(current->thread.regs->msr)) + return; if (current->thread.regs->msr & MSR_FP) __giveup_fpu(current); if (current->thread.regs->msr & MSR_VEC) -- 2.10.0
[PATCH v5 09/20] selftests/powerpc: Move VMX stack frame macros to header file
Signed-off-by: Cyril Bur--- tools/testing/selftests/powerpc/math/vmx_asm.S | 85 +- tools/testing/selftests/powerpc/vmx_asm.h | 98 ++ 2 files changed, 99 insertions(+), 84 deletions(-) create mode 100644 tools/testing/selftests/powerpc/vmx_asm.h diff --git a/tools/testing/selftests/powerpc/math/vmx_asm.S b/tools/testing/selftests/powerpc/math/vmx_asm.S index 1b8c248..fd74da4 100644 --- a/tools/testing/selftests/powerpc/math/vmx_asm.S +++ b/tools/testing/selftests/powerpc/math/vmx_asm.S @@ -8,90 +8,7 @@ */ #include "../basic_asm.h" - -# POS MUST BE 16 ALIGNED! -#define PUSH_VMX(pos,reg) \ - li reg,pos; \ - stvxv20,reg,sp; \ - addireg,reg,16; \ - stvxv21,reg,sp; \ - addireg,reg,16; \ - stvxv22,reg,sp; \ - addireg,reg,16; \ - stvxv23,reg,sp; \ - addireg,reg,16; \ - stvxv24,reg,sp; \ - addireg,reg,16; \ - stvxv25,reg,sp; \ - addireg,reg,16; \ - stvxv26,reg,sp; \ - addireg,reg,16; \ - stvxv27,reg,sp; \ - addireg,reg,16; \ - stvxv28,reg,sp; \ - addireg,reg,16; \ - stvxv29,reg,sp; \ - addireg,reg,16; \ - stvxv30,reg,sp; \ - addireg,reg,16; \ - stvxv31,reg,sp; - -# POS MUST BE 16 ALIGNED! -#define POP_VMX(pos,reg) \ - li reg,pos; \ - lvx v20,reg,sp; \ - addireg,reg,16; \ - lvx v21,reg,sp; \ - addireg,reg,16; \ - lvx v22,reg,sp; \ - addireg,reg,16; \ - lvx v23,reg,sp; \ - addireg,reg,16; \ - lvx v24,reg,sp; \ - addireg,reg,16; \ - lvx v25,reg,sp; \ - addireg,reg,16; \ - lvx v26,reg,sp; \ - addireg,reg,16; \ - lvx v27,reg,sp; \ - addireg,reg,16; \ - lvx v28,reg,sp; \ - addireg,reg,16; \ - lvx v29,reg,sp; \ - addireg,reg,16; \ - lvx v30,reg,sp; \ - addireg,reg,16; \ - lvx v31,reg,sp; - -# Carefull this will 'clobber' vmx (by design) -# Don't call this from C -FUNC_START(load_vmx) - li r5,0 - lvx v20,r5,r3 - addir5,r5,16 - lvx v21,r5,r3 - addir5,r5,16 - lvx v22,r5,r3 - addir5,r5,16 - lvx v23,r5,r3 - addir5,r5,16 - lvx v24,r5,r3 - addir5,r5,16 - lvx v25,r5,r3 - addir5,r5,16 - lvx v26,r5,r3 - addir5,r5,16 - lvx v27,r5,r3 - addir5,r5,16 - lvx v28,r5,r3 - addir5,r5,16 - lvx v29,r5,r3 - addir5,r5,16 - lvx v30,r5,r3 - addir5,r5,16 - lvx v31,r5,r3 - blr -FUNC_END(load_vmx) +#include "../vmx_asm.h" # Should be safe from C, only touches r4, r5 and v0,v1,v2 FUNC_START(check_vmx) diff --git a/tools/testing/selftests/powerpc/vmx_asm.h b/tools/testing/selftests/powerpc/vmx_asm.h new file mode 100644 index 000..461845dd --- /dev/null +++ b/tools/testing/selftests/powerpc/vmx_asm.h @@ -0,0 +1,98 @@ +/* + * Copyright 2015, Cyril Bur, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include "basic_asm.h" + +/* POS MUST BE 16 ALIGNED! */ +#define PUSH_VMX(pos,reg) \ + li reg,pos; \ + stvxv20,reg,%r1; \ + addireg,reg,16; \ + stvxv21,reg,%r1; \ + addireg,reg,16; \ + stvxv22,reg,%r1; \ + addireg,reg,16; \ + stvxv23,reg,%r1; \ + addireg,reg,16; \ + stvxv24,reg,%r1; \ + addireg,reg,16; \ + stvxv25,reg,%r1; \ + addireg,reg,16; \ + stvxv26,reg,%r1; \ + addireg,reg,16; \ + stvxv27,reg,%r1; \ + addireg,reg,16; \ + stvxv28,reg,%r1; \ + addireg,reg,16; \ + stvxv29,reg,%r1; \ + addireg,reg,16; \ + stvxv30,reg,%r1; \ + addireg,reg,16; \ + stvxv31,reg,%r1; + +/* POS MUST BE 16 ALIGNED! */ +#define POP_VMX(pos,reg) \ + li reg,pos; \ + lvx v20,reg,%r1; \ + addireg,reg,16; \ + lvx v21,reg,%r1; \ + addireg,reg,16; \ + lvx v22,reg,%r1; \ + addireg,reg,16; \ + lvx v23,reg,%r1; \ + addireg,reg,16; \ + lvx v24,reg,%r1; \ + addireg,reg,16; \ + lvx v25,reg,%r1; \ + addireg,reg,16; \ + lvx v26,reg,%r1; \ + addireg,reg,16; \ + lvx v27,reg,%r1; \ + addireg,reg,16; \ + lvx v28,reg,%r1; \ + addireg,reg,16; \ +
[PATCH v5 07/20] selftests/powerpc: Check for VSX preservation across userspace preemption
Ensure the kernel correctly switches VSX registers correctly. VSX registers are all volatile, and despite the kernel preserving VSX across syscalls, it doesn't have to. Test that during interrupts and timeslices ending the VSX regs remain the same. Signed-off-by: Cyril Bur--- tools/testing/selftests/powerpc/math/Makefile | 4 +- tools/testing/selftests/powerpc/math/vsx_asm.S | 61 + tools/testing/selftests/powerpc/math/vsx_preempt.c | 147 + tools/testing/selftests/powerpc/vsx_asm.h | 71 ++ 4 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/powerpc/math/vsx_asm.S create mode 100644 tools/testing/selftests/powerpc/math/vsx_preempt.c create mode 100644 tools/testing/selftests/powerpc/vsx_asm.h diff --git a/tools/testing/selftests/powerpc/math/Makefile b/tools/testing/selftests/powerpc/math/Makefile index 5b88875..aa6598b 100644 --- a/tools/testing/selftests/powerpc/math/Makefile +++ b/tools/testing/selftests/powerpc/math/Makefile @@ -1,4 +1,4 @@ -TEST_PROGS := fpu_syscall fpu_preempt fpu_signal vmx_syscall vmx_preempt vmx_signal +TEST_PROGS := fpu_syscall fpu_preempt fpu_signal vmx_syscall vmx_preempt vmx_signal vsx_preempt all: $(TEST_PROGS) @@ -13,6 +13,8 @@ vmx_syscall: vmx_asm.S vmx_preempt: vmx_asm.S vmx_signal: vmx_asm.S +vsx_preempt: vsx_asm.S + include ../../lib.mk clean: diff --git a/tools/testing/selftests/powerpc/math/vsx_asm.S b/tools/testing/selftests/powerpc/math/vsx_asm.S new file mode 100644 index 000..a110dd8 --- /dev/null +++ b/tools/testing/selftests/powerpc/math/vsx_asm.S @@ -0,0 +1,61 @@ +/* + * Copyright 2015, Cyril Bur, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include "../basic_asm.h" +#include "../vsx_asm.h" + +#long check_vsx(vector int *r3); +#This function wraps storeing VSX regs to the end of an array and a +#call to a comparison function in C which boils down to a memcmp() +FUNC_START(check_vsx) + PUSH_BASIC_STACK(32) + std r3,STACK_FRAME_PARAM(0)(sp) + addi r3, r3, 16 * 12 #Second half of array + bl store_vsx + ld r3,STACK_FRAME_PARAM(0)(sp) + bl vsx_memcmp + POP_BASIC_STACK(32) + blr +FUNC_END(check_vsx) + +# int preempt_vmx(vector int *varray, int *threads_starting, +# int *running); +# On starting will (atomically) decrement threads_starting as a signal +# that the VMX have been loaded with varray. Will proceed to check the +# validity of the VMX registers while running is not zero. +FUNC_START(preempt_vsx) + PUSH_BASIC_STACK(512) + std r3,STACK_FRAME_PARAM(0)(sp) # vector int *varray + std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting + std r5,STACK_FRAME_PARAM(2)(sp) # int *running + + bl load_vsx + nop + + sync + # Atomic DEC + ld r3,STACK_FRAME_PARAM(1)(sp) +1: lwarx r4,0,r3 + addi r4,r4,-1 + stwcx. r4,0,r3 + bne- 1b + +2: ld r3,STACK_FRAME_PARAM(0)(sp) + bl check_vsx + nop + cmpdi r3,0 + bne 3f + ld r4,STACK_FRAME_PARAM(2)(sp) + ld r5,0(r4) + cmpwi r5,0 + bne 2b + +3: POP_BASIC_STACK(512) + blr +FUNC_END(preempt_vsx) diff --git a/tools/testing/selftests/powerpc/math/vsx_preempt.c b/tools/testing/selftests/powerpc/math/vsx_preempt.c new file mode 100644 index 000..6387f03 --- /dev/null +++ b/tools/testing/selftests/powerpc/math/vsx_preempt.c @@ -0,0 +1,147 @@ +/* + * Copyright 2015, Cyril Bur, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * This test attempts to see if the VSX registers change across preemption. + * There is no way to be sure preemption happened so this test just + * uses many threads and a long wait. As such, a successful test + * doesn't mean much but a failure is bad. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" + +/* Time to wait for workers to get preempted (seconds) */ +#define PREEMPT_TIME 20 +/* + * Factor by which to multiply number of online CPUs for total number of + * worker threads + */ +#define THREAD_FACTOR 8 + +/* + * Ensure there is twice the number of non-volatile VMX regs! + * check_vmx() is going to use the other half as space to put the live + * registers before calling vsx_memcmp() + */ +__thread vector int varray[24] = { + {1, 2, 3, 4 }, {5, 6, 7, 8 }, {9, 10,11,12}, + {13,14,15,16}, {17,18,19,20}, {21,22,23,24}, +
[PATCH v5 15/20] selftests/powerpc: Add checks for transactional FPUs in signal contexts
If a thread receives a signal while transactional the kernel creates a second context to show the transactional state of the process. This test loads some known values and waits for a signal and confirms that the expected values are in the signal context. Signed-off-by: Cyril Bur--- tools/testing/selftests/powerpc/tm/Makefile| 2 +- .../powerpc/tm/tm-signal-context-chk-fpu.c | 92 ++ 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile index 2b6fe8f..103648f 100644 --- a/tools/testing/selftests/powerpc/tm/Makefile +++ b/tools/testing/selftests/powerpc/tm/Makefile @@ -1,4 +1,4 @@ -SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr +SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr tm-signal-context-chk-fpu TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \ tm-vmxcopy tm-fork tm-tar tm-tmspr $(SIGNAL_CONTEXT_CHK_TESTS) diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c new file mode 100644 index 000..c760deb --- /dev/null +++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c @@ -0,0 +1,92 @@ +/* + * Copyright 2016, Cyril Bur, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * + * Test the kernel's signal frame code. + * + * The kernel sets up two sets of ucontexts if the signal was to be + * delivered while the thread was in a transaction. + * Expected behaviour is that the checkpointed state is in the user + * context passed to the signal handler. The speculated state can be + * accessed with the uc_link pointer. + * + * The rationale for this is that if TM unaware code (which linked + * against TM libs) installs a signal handler it will not know of the + * speculative nature of the 'live' registers and may infer the wrong + * thing. + */ + +#include +#include +#include +#include + +#include + +#include "utils.h" +#include "tm.h" + +#define MAX_ATTEMPT 50 + +#define NV_FPU_REGS 18 + +long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss); + +/* Be sure there are 2x as many as there are NV FPU regs (2x18) */ +static double fps[] = { +1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18 +}; + +static sig_atomic_t fail; + +static void signal_usr1(int signum, siginfo_t *info, void *uc) +{ + int i; + ucontext_t *ucp = uc; + ucontext_t *tm_ucp = ucp->uc_link; + + for (i = 0; i < NV_FPU_REGS && !fail; i++) { + fail = (ucp->uc_mcontext.fp_regs[i + 14] != fps[i]); + fail |= (tm_ucp->uc_mcontext.fp_regs[i + 14] != fps[i + NV_FPU_REGS]); + if (fail) + printf("Failed on %d FP %g or %g\n", i, ucp->uc_mcontext.fp_regs[i + 14], tm_ucp->uc_mcontext.fp_regs[i + 14]); + } +} + +static int tm_signal_context_chk_fpu() +{ + struct sigaction act; + int i; + long rc; + pid_t pid = getpid(); + + SKIP_IF(!have_htm()); + + act.sa_sigaction = signal_usr1; + sigemptyset(_mask); + act.sa_flags = SA_SIGINFO; + if (sigaction(SIGUSR1, , NULL) < 0) { + perror("sigaction sigusr1"); + exit(1); + } + + i = 0; + while (i < MAX_ATTEMPT && !fail) { + rc = tm_signal_self_context_load(pid, NULL, fps, NULL, NULL); + FAIL_IF(rc != pid); + i++; + } + + return fail; +} + +int main(void) +{ + return test_harness(tm_signal_context_chk_fpu, "tm_signal_context_chk_fpu"); +} -- 2.10.0
[PATCH v5 16/20] selftests/powerpc: Add checks for transactional VMXs in signal contexts
If a thread receives a signal while transactional the kernel creates a second context to show the transactional state of the process. This test loads some known values and waits for a signal and confirms that the expected values are in the signal context. Signed-off-by: Cyril Bur--- tools/testing/selftests/powerpc/tm/Makefile| 3 +- .../powerpc/tm/tm-signal-context-chk-vmx.c | 110 + 2 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile index 103648f..06c44aa 100644 --- a/tools/testing/selftests/powerpc/tm/Makefile +++ b/tools/testing/selftests/powerpc/tm/Makefile @@ -1,4 +1,5 @@ -SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr tm-signal-context-chk-fpu +SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr tm-signal-context-chk-fpu \ + tm-signal-context-chk-vmx TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \ tm-vmxcopy tm-fork tm-tar tm-tmspr $(SIGNAL_CONTEXT_CHK_TESTS) diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c new file mode 100644 index 000..f0ee55f --- /dev/null +++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c @@ -0,0 +1,110 @@ +/* + * Copyright 2016, Cyril Bur, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * + * Test the kernel's signal frame code. + * + * The kernel sets up two sets of ucontexts if the signal was to be + * delivered while the thread was in a transaction. + * Expected behaviour is that the checkpointed state is in the user + * context passed to the signal handler. The speculated state can be + * accessed with the uc_link pointer. + * + * The rationale for this is that if TM unaware code (which linked + * against TM libs) installs a signal handler it will not know of the + * speculative nature of the 'live' registers and may infer the wrong + * thing. + */ + +#include +#include +#include +#include +#include + +#include + +#include "utils.h" +#include "tm.h" + +#define MAX_ATTEMPT 50 + +#define NV_VMX_REGS 12 + +long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss); + +static sig_atomic_t fail; + +vector int vms[] = { + {1, 2, 3, 4 },{5, 6, 7, 8 },{9, 10,11,12}, + {13,14,15,16},{17,18,19,20},{21,22,23,24}, + {25,26,27,28},{29,30,31,32},{33,34,35,36}, + {37,38,39,40},{41,42,43,44},{45,46,47,48}, + {-1, -2, -3, -4}, {-5, -6, -7, -8}, {-9, -10,-11,-12}, + {-13,-14,-15,-16},{-17,-18,-19,-20},{-21,-22,-23,-24}, + {-25,-26,-27,-28},{-29,-30,-31,-32},{-33,-34,-35,-36}, + {-37,-38,-39,-40},{-41,-42,-43,-44},{-45,-46,-47,-48} +}; + +static void signal_usr1(int signum, siginfo_t *info, void *uc) +{ + int i; + ucontext_t *ucp = uc; + ucontext_t *tm_ucp = ucp->uc_link; + + for (i = 0; i < NV_VMX_REGS && !fail; i++) { + fail = memcmp(ucp->uc_mcontext.v_regs->vrregs[i + 20], + [i], sizeof(vector int)); + fail |= memcmp(tm_ucp->uc_mcontext.v_regs->vrregs[i + 20], + [i + NV_VMX_REGS], sizeof (vector int)); + + if (fail) { + int j; + + fprintf(stderr, "Failed on %d vmx 0x", i); + for (j = 0; j < 4; j++) + fprintf(stderr, "%04x", ucp->uc_mcontext.v_regs->vrregs[i + 20][j]); + fprintf(stderr, " vs 0x"); + for (j = 0 ; j < 4; j++) + fprintf(stderr, "%04x", tm_ucp->uc_mcontext.v_regs->vrregs[i + 20][j]); + fprintf(stderr, "\n"); + } + } +} + +static int tm_signal_context_chk() +{ + struct sigaction act; + int i; + long rc; + pid_t pid = getpid(); + + SKIP_IF(!have_htm()); + + act.sa_sigaction = signal_usr1; + sigemptyset(_mask); + act.sa_flags = SA_SIGINFO; + if (sigaction(SIGUSR1, , NULL) < 0) { + perror("sigaction sigusr1"); + exit(1); + } + + i = 0; + while (i < MAX_ATTEMPT && !fail) { + rc = tm_signal_self_context_load(pid, NULL, NULL, vms, NULL); + FAIL_IF(rc != pid); + i++; + } + + return fail; +} + +int main(void) +{ + return test_harness(tm_signal_context_chk, "tm_signal_context_chk_vmx"); +} -- 2.10.0
[PATCH v5 08/20] selftests/powerpc: Rework FPU stack placement macros and move to header file
The FPU regs are placed at the top of the stack frame. Currently the position expected to be passed to the macro. The macros now should be passed the stack frame size and from there they can calculate where to put the regs, this makes the use simpler. Also move them to a header file to be used in an different area of the powerpc selftests Signed-off-by: Cyril Bur--- tools/testing/selftests/powerpc/fpu_asm.h | 81 ++ tools/testing/selftests/powerpc/math/fpu_asm.S | 73 ++- 2 files changed, 86 insertions(+), 68 deletions(-) create mode 100644 tools/testing/selftests/powerpc/fpu_asm.h diff --git a/tools/testing/selftests/powerpc/fpu_asm.h b/tools/testing/selftests/powerpc/fpu_asm.h new file mode 100644 index 000..24061b8 --- /dev/null +++ b/tools/testing/selftests/powerpc/fpu_asm.h @@ -0,0 +1,81 @@ +/* + * Copyright 2016, Cyril Bur, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _SELFTESTS_POWERPC_FPU_ASM_H +#define _SELFTESTS_POWERPC_FPU_ASM_H +#include "basic_asm.h" + +#define PUSH_FPU(stack_size) \ + stfdf31,(stack_size + STACK_FRAME_MIN_SIZE)(%r1); \ + stfdf30,(stack_size + STACK_FRAME_MIN_SIZE - 8)(%r1); \ + stfdf29,(stack_size + STACK_FRAME_MIN_SIZE - 16)(%r1); \ + stfdf28,(stack_size + STACK_FRAME_MIN_SIZE - 24)(%r1); \ + stfdf27,(stack_size + STACK_FRAME_MIN_SIZE - 32)(%r1); \ + stfdf26,(stack_size + STACK_FRAME_MIN_SIZE - 40)(%r1); \ + stfdf25,(stack_size + STACK_FRAME_MIN_SIZE - 48)(%r1); \ + stfdf24,(stack_size + STACK_FRAME_MIN_SIZE - 56)(%r1); \ + stfdf23,(stack_size + STACK_FRAME_MIN_SIZE - 64)(%r1); \ + stfdf22,(stack_size + STACK_FRAME_MIN_SIZE - 72)(%r1); \ + stfdf21,(stack_size + STACK_FRAME_MIN_SIZE - 80)(%r1); \ + stfdf20,(stack_size + STACK_FRAME_MIN_SIZE - 88)(%r1); \ + stfdf19,(stack_size + STACK_FRAME_MIN_SIZE - 96)(%r1); \ + stfdf18,(stack_size + STACK_FRAME_MIN_SIZE - 104)(%r1); \ + stfdf17,(stack_size + STACK_FRAME_MIN_SIZE - 112)(%r1); \ + stfdf16,(stack_size + STACK_FRAME_MIN_SIZE - 120)(%r1); \ + stfdf15,(stack_size + STACK_FRAME_MIN_SIZE - 128)(%r1); \ + stfdf14,(stack_size + STACK_FRAME_MIN_SIZE - 136)(%r1); + +#define POP_FPU(stack_size) \ + lfd f31,(stack_size + STACK_FRAME_MIN_SIZE)(%r1); \ + lfd f30,(stack_size + STACK_FRAME_MIN_SIZE - 8)(%r1); \ + lfd f29,(stack_size + STACK_FRAME_MIN_SIZE - 16)(%r1); \ + lfd f28,(stack_size + STACK_FRAME_MIN_SIZE - 24)(%r1); \ + lfd f27,(stack_size + STACK_FRAME_MIN_SIZE - 32)(%r1); \ + lfd f26,(stack_size + STACK_FRAME_MIN_SIZE - 40)(%r1); \ + lfd f25,(stack_size + STACK_FRAME_MIN_SIZE - 48)(%r1); \ + lfd f24,(stack_size + STACK_FRAME_MIN_SIZE - 56)(%r1); \ + lfd f23,(stack_size + STACK_FRAME_MIN_SIZE - 64)(%r1); \ + lfd f22,(stack_size + STACK_FRAME_MIN_SIZE - 72)(%r1); \ + lfd f21,(stack_size + STACK_FRAME_MIN_SIZE - 80)(%r1); \ + lfd f20,(stack_size + STACK_FRAME_MIN_SIZE - 88)(%r1); \ + lfd f19,(stack_size + STACK_FRAME_MIN_SIZE - 96)(%r1); \ + lfd f18,(stack_size + STACK_FRAME_MIN_SIZE - 104)(%r1); \ + lfd f17,(stack_size + STACK_FRAME_MIN_SIZE - 112)(%r1); \ + lfd f16,(stack_size + STACK_FRAME_MIN_SIZE - 120)(%r1); \ + lfd f15,(stack_size + STACK_FRAME_MIN_SIZE - 128)(%r1); \ + lfd f14,(stack_size + STACK_FRAME_MIN_SIZE - 136)(%r1); + +/* + * Careful calling this, it will 'clobber' fpu (by design) + * Don't call this from C + */ +FUNC_START(load_fpu) + lfd f14,0(r3) + lfd f15,8(r3) + lfd f16,16(r3) + lfd f17,24(r3) + lfd f18,32(r3) + lfd f19,40(r3) + lfd f20,48(r3) + lfd f21,56(r3) + lfd f22,64(r3) + lfd f23,72(r3) + lfd f24,80(r3) + lfd f25,88(r3) + lfd f26,96(r3) + lfd f27,104(r3) + lfd f28,112(r3) + lfd f29,120(r3) + lfd f30,128(r3) + lfd f31,136(r3) + blr +FUNC_END(load_fpu) + +#endif /* _SELFTESTS_POWERPC_FPU_ASM_H */ + diff --git a/tools/testing/selftests/powerpc/math/fpu_asm.S b/tools/testing/selftests/powerpc/math/fpu_asm.S index f3711d8..241f067 100644 --- a/tools/testing/selftests/powerpc/math/fpu_asm.S +++ b/tools/testing/selftests/powerpc/math/fpu_asm.S @@ -8,70 +8,7 @@ */ #include "../basic_asm.h" - -#define PUSH_FPU(pos) \ - stfdf14,pos(sp); \ - stfdf15,pos+8(sp); \ - stfdf16,pos+16(sp); \ - stfdf17,pos+24(sp); \ -