Re: [PATCH v3 09/14] powerpc/xmon: Add initial support for prefixed instructions
Jordan Niethe's on February 28, 2020 10:37 am: > On Thu, Feb 27, 2020 at 6:14 PM Christophe Leroy > wrote: >> >> >> >> Le 27/02/2020 à 01:11, Jordan Niethe a écrit : >> > On Wed, Feb 26, 2020 at 6:10 PM Nicholas Piggin wrote: >> >> >> >> Jordan Niethe's on February 26, 2020 2:07 pm: >> >>> A prefixed instruction is composed of a word prefix and a word suffix. >> >>> It does not make sense to be able to have a breakpoint on the suffix of >> >>> a prefixed instruction, so make this impossible. >> >>> >> >>> When leaving xmon_core() we check to see if we are currently at a >> >>> breakpoint. If this is the case, the breakpoint needs to be proceeded >> >>> from. Initially emulate_step() is tried, but if this fails then we need >> >>> to execute the saved instruction out of line. The NIP is set to the >> >>> address of bpt::instr[] for the current breakpoint. bpt::instr[] >> >>> contains the instruction replaced by the breakpoint, followed by a trap >> >>> instruction. After bpt::instr[0] is executed and we hit the trap we >> >>> enter back into xmon_bpt(). We know that if we got here and the offset >> >>> indicates we are at bpt::instr[1] then we have just executed out of line >> >>> so we can put the NIP back to the instruction after the breakpoint >> >>> location and continue on. >> >>> >> >>> Adding prefixed instructions complicates this as the bpt::instr[1] needs >> >>> to be used to hold the suffix. To deal with this make bpt::instr[] big >> >>> enough for three word instructions. bpt::instr[2] contains the trap, >> >>> and in the case of word instructions pad bpt::instr[1] with a noop. >> >>> >> >>> No support for disassembling prefixed instructions. >> >>> >> >>> Signed-off-by: Jordan Niethe >> >>> --- >> >>> v2: Rename sufx to suffix >> >>> v3: - Just directly use PPC_INST_NOP >> >>> - Typo: plac -> place >> >>> - Rename read_inst() to mread_inst(). Do not have it call mread(). >> >>> --- >> >>> arch/powerpc/xmon/xmon.c | 90 ++-- >> >>> 1 file changed, 78 insertions(+), 12 deletions(-) >> >>> >> >>> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c >> >>> index a673cf55641c..a73a35aa4a75 100644 >> >>> --- a/arch/powerpc/xmon/xmon.c >> >>> +++ b/arch/powerpc/xmon/xmon.c >> >>> @@ -97,7 +97,8 @@ static long *xmon_fault_jmp[NR_CPUS]; >> >>> /* Breakpoint stuff */ >> >>> struct bpt { >> >>>unsigned long address; >> >>> - unsigned intinstr[2]; >> >>> + /* Prefixed instructions can not cross 64-byte boundaries */ >> >>> + unsigned intinstr[3] __aligned(64); >> >> >> >> This is pretty wild, I didn't realize xmon executes breakpoints out >> >> of line like this. >> >> Neither did I. That's problematic. Kernel data is mapped NX on some >> platforms. >> >> >> >> >> IMO the break point entries here should correspond with a range of >> >> reserved bytes in .text so we patch instructions into normal executable >> >> pages rather than .data. >> > Would it make sense to use vmalloc_exec() and use that like we are >> > going to do in kprobes()? >> >> As we are (already) doing in kprobes() you mean ? > Sorry for the confusion, I was mainly thinking of the patch that you > pointed out before: > https://patchwork.ozlabs.org/patch/1232619/ >> >> In fact kprobes uses module_alloc(), and it works because kprobe depends >> on module. On some platforms (i.e. book3s/32) vmalloc space is marked NX >> in segment registers when CONFIG_MODULES is not set, see >> mmu_mark_initmem_nx(). On other ones the Instruction TLB miss exception >> does not manage misses at kernel addresses when CONFIG_MODULES is not >> selected. >> >> So if we want XMON to work at all time, we need to use some (linear) >> text address and use patch_instruction() to change it. > Thank you for the detailed clarification, I will do it like that. Yeah I would just make a little array in .text.xmon_bpts or something, which should do the trick. That wouldn't depend on this series, but if you want to do it as a fix up patch before it, that would be good. Thanks, Nick
Re: [PATCH v3 09/14] powerpc/xmon: Add initial support for prefixed instructions
On Thu, Feb 27, 2020 at 6:14 PM Christophe Leroy wrote: > > > > Le 27/02/2020 à 01:11, Jordan Niethe a écrit : > > On Wed, Feb 26, 2020 at 6:10 PM Nicholas Piggin wrote: > >> > >> Jordan Niethe's on February 26, 2020 2:07 pm: > >>> A prefixed instruction is composed of a word prefix and a word suffix. > >>> It does not make sense to be able to have a breakpoint on the suffix of > >>> a prefixed instruction, so make this impossible. > >>> > >>> When leaving xmon_core() we check to see if we are currently at a > >>> breakpoint. If this is the case, the breakpoint needs to be proceeded > >>> from. Initially emulate_step() is tried, but if this fails then we need > >>> to execute the saved instruction out of line. The NIP is set to the > >>> address of bpt::instr[] for the current breakpoint. bpt::instr[] > >>> contains the instruction replaced by the breakpoint, followed by a trap > >>> instruction. After bpt::instr[0] is executed and we hit the trap we > >>> enter back into xmon_bpt(). We know that if we got here and the offset > >>> indicates we are at bpt::instr[1] then we have just executed out of line > >>> so we can put the NIP back to the instruction after the breakpoint > >>> location and continue on. > >>> > >>> Adding prefixed instructions complicates this as the bpt::instr[1] needs > >>> to be used to hold the suffix. To deal with this make bpt::instr[] big > >>> enough for three word instructions. bpt::instr[2] contains the trap, > >>> and in the case of word instructions pad bpt::instr[1] with a noop. > >>> > >>> No support for disassembling prefixed instructions. > >>> > >>> Signed-off-by: Jordan Niethe > >>> --- > >>> v2: Rename sufx to suffix > >>> v3: - Just directly use PPC_INST_NOP > >>> - Typo: plac -> place > >>> - Rename read_inst() to mread_inst(). Do not have it call mread(). > >>> --- > >>> arch/powerpc/xmon/xmon.c | 90 ++-- > >>> 1 file changed, 78 insertions(+), 12 deletions(-) > >>> > >>> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c > >>> index a673cf55641c..a73a35aa4a75 100644 > >>> --- a/arch/powerpc/xmon/xmon.c > >>> +++ b/arch/powerpc/xmon/xmon.c > >>> @@ -97,7 +97,8 @@ static long *xmon_fault_jmp[NR_CPUS]; > >>> /* Breakpoint stuff */ > >>> struct bpt { > >>>unsigned long address; > >>> - unsigned intinstr[2]; > >>> + /* Prefixed instructions can not cross 64-byte boundaries */ > >>> + unsigned intinstr[3] __aligned(64); > >> > >> This is pretty wild, I didn't realize xmon executes breakpoints out > >> of line like this. > > Neither did I. That's problematic. Kernel data is mapped NX on some > platforms. > > >> > >> IMO the break point entries here should correspond with a range of > >> reserved bytes in .text so we patch instructions into normal executable > >> pages rather than .data. > > Would it make sense to use vmalloc_exec() and use that like we are > > going to do in kprobes()? > > As we are (already) doing in kprobes() you mean ? Sorry for the confusion, I was mainly thinking of the patch that you pointed out before: https://patchwork.ozlabs.org/patch/1232619/ > > In fact kprobes uses module_alloc(), and it works because kprobe depends > on module. On some platforms (i.e. book3s/32) vmalloc space is marked NX > in segment registers when CONFIG_MODULES is not set, see > mmu_mark_initmem_nx(). On other ones the Instruction TLB miss exception > does not manage misses at kernel addresses when CONFIG_MODULES is not > selected. > > So if we want XMON to work at all time, we need to use some (linear) > text address and use patch_instruction() to change it. Thank you for the detailed clarification, I will do it like that. > > Christophe > > >> > >> Anyway that's for patch. > >> > >> Thanks, > >> Nick
Re: [PATCH v3 09/14] powerpc/xmon: Add initial support for prefixed instructions
Le 27/02/2020 à 01:11, Jordan Niethe a écrit : On Wed, Feb 26, 2020 at 6:10 PM Nicholas Piggin wrote: Jordan Niethe's on February 26, 2020 2:07 pm: A prefixed instruction is composed of a word prefix and a word suffix. It does not make sense to be able to have a breakpoint on the suffix of a prefixed instruction, so make this impossible. When leaving xmon_core() we check to see if we are currently at a breakpoint. If this is the case, the breakpoint needs to be proceeded from. Initially emulate_step() is tried, but if this fails then we need to execute the saved instruction out of line. The NIP is set to the address of bpt::instr[] for the current breakpoint. bpt::instr[] contains the instruction replaced by the breakpoint, followed by a trap instruction. After bpt::instr[0] is executed and we hit the trap we enter back into xmon_bpt(). We know that if we got here and the offset indicates we are at bpt::instr[1] then we have just executed out of line so we can put the NIP back to the instruction after the breakpoint location and continue on. Adding prefixed instructions complicates this as the bpt::instr[1] needs to be used to hold the suffix. To deal with this make bpt::instr[] big enough for three word instructions. bpt::instr[2] contains the trap, and in the case of word instructions pad bpt::instr[1] with a noop. No support for disassembling prefixed instructions. Signed-off-by: Jordan Niethe --- v2: Rename sufx to suffix v3: - Just directly use PPC_INST_NOP - Typo: plac -> place - Rename read_inst() to mread_inst(). Do not have it call mread(). --- arch/powerpc/xmon/xmon.c | 90 ++-- 1 file changed, 78 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index a673cf55641c..a73a35aa4a75 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -97,7 +97,8 @@ static long *xmon_fault_jmp[NR_CPUS]; /* Breakpoint stuff */ struct bpt { unsigned long address; - unsigned intinstr[2]; + /* Prefixed instructions can not cross 64-byte boundaries */ + unsigned intinstr[3] __aligned(64); This is pretty wild, I didn't realize xmon executes breakpoints out of line like this. Neither did I. That's problematic. Kernel data is mapped NX on some platforms. IMO the break point entries here should correspond with a range of reserved bytes in .text so we patch instructions into normal executable pages rather than .data. Would it make sense to use vmalloc_exec() and use that like we are going to do in kprobes()? As we are (already) doing in kprobes() you mean ? In fact kprobes uses module_alloc(), and it works because kprobe depends on module. On some platforms (i.e. book3s/32) vmalloc space is marked NX in segment registers when CONFIG_MODULES is not set, see mmu_mark_initmem_nx(). On other ones the Instruction TLB miss exception does not manage misses at kernel addresses when CONFIG_MODULES is not selected. So if we want XMON to work at all time, we need to use some (linear) text address and use patch_instruction() to change it. Christophe Anyway that's for patch. Thanks, Nick
Re: [PATCH v3 09/14] powerpc/xmon: Add initial support for prefixed instructions
On Wed, Feb 26, 2020 at 6:10 PM Nicholas Piggin wrote: > > Jordan Niethe's on February 26, 2020 2:07 pm: > > A prefixed instruction is composed of a word prefix and a word suffix. > > It does not make sense to be able to have a breakpoint on the suffix of > > a prefixed instruction, so make this impossible. > > > > When leaving xmon_core() we check to see if we are currently at a > > breakpoint. If this is the case, the breakpoint needs to be proceeded > > from. Initially emulate_step() is tried, but if this fails then we need > > to execute the saved instruction out of line. The NIP is set to the > > address of bpt::instr[] for the current breakpoint. bpt::instr[] > > contains the instruction replaced by the breakpoint, followed by a trap > > instruction. After bpt::instr[0] is executed and we hit the trap we > > enter back into xmon_bpt(). We know that if we got here and the offset > > indicates we are at bpt::instr[1] then we have just executed out of line > > so we can put the NIP back to the instruction after the breakpoint > > location and continue on. > > > > Adding prefixed instructions complicates this as the bpt::instr[1] needs > > to be used to hold the suffix. To deal with this make bpt::instr[] big > > enough for three word instructions. bpt::instr[2] contains the trap, > > and in the case of word instructions pad bpt::instr[1] with a noop. > > > > No support for disassembling prefixed instructions. > > > > Signed-off-by: Jordan Niethe > > --- > > v2: Rename sufx to suffix > > v3: - Just directly use PPC_INST_NOP > > - Typo: plac -> place > > - Rename read_inst() to mread_inst(). Do not have it call mread(). > > --- > > arch/powerpc/xmon/xmon.c | 90 ++-- > > 1 file changed, 78 insertions(+), 12 deletions(-) > > > > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c > > index a673cf55641c..a73a35aa4a75 100644 > > --- a/arch/powerpc/xmon/xmon.c > > +++ b/arch/powerpc/xmon/xmon.c > > @@ -97,7 +97,8 @@ static long *xmon_fault_jmp[NR_CPUS]; > > /* Breakpoint stuff */ > > struct bpt { > > unsigned long address; > > - unsigned intinstr[2]; > > + /* Prefixed instructions can not cross 64-byte boundaries */ > > + unsigned intinstr[3] __aligned(64); > > This is pretty wild, I didn't realize xmon executes breakpoints out > of line like this. > > IMO the break point entries here should correspond with a range of > reserved bytes in .text so we patch instructions into normal executable > pages rather than .data. Would it make sense to use vmalloc_exec() and use that like we are going to do in kprobes()? > > Anyway that's for patch. > > Thanks, > Nick
Re: [PATCH v3 09/14] powerpc/xmon: Add initial support for prefixed instructions
Jordan Niethe's on February 26, 2020 2:07 pm: > A prefixed instruction is composed of a word prefix and a word suffix. > It does not make sense to be able to have a breakpoint on the suffix of > a prefixed instruction, so make this impossible. > > When leaving xmon_core() we check to see if we are currently at a > breakpoint. If this is the case, the breakpoint needs to be proceeded > from. Initially emulate_step() is tried, but if this fails then we need > to execute the saved instruction out of line. The NIP is set to the > address of bpt::instr[] for the current breakpoint. bpt::instr[] > contains the instruction replaced by the breakpoint, followed by a trap > instruction. After bpt::instr[0] is executed and we hit the trap we > enter back into xmon_bpt(). We know that if we got here and the offset > indicates we are at bpt::instr[1] then we have just executed out of line > so we can put the NIP back to the instruction after the breakpoint > location and continue on. > > Adding prefixed instructions complicates this as the bpt::instr[1] needs > to be used to hold the suffix. To deal with this make bpt::instr[] big > enough for three word instructions. bpt::instr[2] contains the trap, > and in the case of word instructions pad bpt::instr[1] with a noop. > > No support for disassembling prefixed instructions. > > Signed-off-by: Jordan Niethe > --- > v2: Rename sufx to suffix > v3: - Just directly use PPC_INST_NOP > - Typo: plac -> place > - Rename read_inst() to mread_inst(). Do not have it call mread(). > --- > arch/powerpc/xmon/xmon.c | 90 ++-- > 1 file changed, 78 insertions(+), 12 deletions(-) > > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c > index a673cf55641c..a73a35aa4a75 100644 > --- a/arch/powerpc/xmon/xmon.c > +++ b/arch/powerpc/xmon/xmon.c > @@ -97,7 +97,8 @@ static long *xmon_fault_jmp[NR_CPUS]; > /* Breakpoint stuff */ > struct bpt { > unsigned long address; > - unsigned intinstr[2]; > + /* Prefixed instructions can not cross 64-byte boundaries */ > + unsigned intinstr[3] __aligned(64); This is pretty wild, I didn't realize xmon executes breakpoints out of line like this. IMO the break point entries here should correspond with a range of reserved bytes in .text so we patch instructions into normal executable pages rather than .data. Anyway that's for patch. Thanks, Nick
[PATCH v3 09/14] powerpc/xmon: Add initial support for prefixed instructions
A prefixed instruction is composed of a word prefix and a word suffix. It does not make sense to be able to have a breakpoint on the suffix of a prefixed instruction, so make this impossible. When leaving xmon_core() we check to see if we are currently at a breakpoint. If this is the case, the breakpoint needs to be proceeded from. Initially emulate_step() is tried, but if this fails then we need to execute the saved instruction out of line. The NIP is set to the address of bpt::instr[] for the current breakpoint. bpt::instr[] contains the instruction replaced by the breakpoint, followed by a trap instruction. After bpt::instr[0] is executed and we hit the trap we enter back into xmon_bpt(). We know that if we got here and the offset indicates we are at bpt::instr[1] then we have just executed out of line so we can put the NIP back to the instruction after the breakpoint location and continue on. Adding prefixed instructions complicates this as the bpt::instr[1] needs to be used to hold the suffix. To deal with this make bpt::instr[] big enough for three word instructions. bpt::instr[2] contains the trap, and in the case of word instructions pad bpt::instr[1] with a noop. No support for disassembling prefixed instructions. Signed-off-by: Jordan Niethe --- v2: Rename sufx to suffix v3: - Just directly use PPC_INST_NOP - Typo: plac -> place - Rename read_inst() to mread_inst(). Do not have it call mread(). --- arch/powerpc/xmon/xmon.c | 90 ++-- 1 file changed, 78 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index a673cf55641c..a73a35aa4a75 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -97,7 +97,8 @@ static long *xmon_fault_jmp[NR_CPUS]; /* Breakpoint stuff */ struct bpt { unsigned long address; - unsigned intinstr[2]; + /* Prefixed instructions can not cross 64-byte boundaries */ + unsigned intinstr[3] __aligned(64); atomic_tref_count; int enabled; unsigned long pad; @@ -120,6 +121,7 @@ static unsigned bpinstr = 0x7fe8; /* trap */ static int cmds(struct pt_regs *); static int mread(unsigned long, void *, int); static int mwrite(unsigned long, void *, int); +static int mread_instr(unsigned long, unsigned int *, unsigned int *); static int handle_fault(struct pt_regs *); static void byterev(unsigned char *, int); static void memex(void); @@ -701,7 +703,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi) bp = at_breakpoint(regs->nip); if (bp != NULL) { int stepped = emulate_step(regs, bp->instr[0], - PPC_NO_SUFFIX); + bp->instr[1]); if (stepped == 0) { regs->nip = (unsigned long) >instr[0]; atomic_inc(>ref_count); @@ -756,8 +758,8 @@ static int xmon_bpt(struct pt_regs *regs) /* Are we at the trap at bp->instr[1] for some bp? */ bp = in_breakpoint_table(regs->nip, ); - if (bp != NULL && offset == 4) { - regs->nip = bp->address + 4; + if (bp != NULL && (offset == 4 || offset == 8)) { + regs->nip = bp->address + offset; atomic_dec(>ref_count); return 1; } @@ -858,8 +860,9 @@ static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp) if (off >= sizeof(bpts)) return NULL; off %= sizeof(struct bpt); - if (off != offsetof(struct bpt, instr[0]) - && off != offsetof(struct bpt, instr[1])) + if (off != offsetof(struct bpt, instr[0]) && + off != offsetof(struct bpt, instr[1]) && + off != offsetof(struct bpt, instr[2])) return NULL; *offp = off - offsetof(struct bpt, instr[0]); return (struct bpt *) (nip - off); @@ -876,8 +879,16 @@ static struct bpt *new_breakpoint(unsigned long a) for (bp = bpts; bp < [NBPTS]; ++bp) { if (!bp->enabled && atomic_read(>ref_count) == 0) { + /* +* Prefixed instructions are two words, but regular +* instructions are only one. Use a nop to pad out the +* regular instructions so that we can place the trap +* at the same place. For prefixed instructions the nop +* will get overwritten during insert_bpts(). +*/ bp->address = a; - patch_instruction(>instr[1], bpinstr); + patch_instruction(>instr[1], PPC_INST_NOP); + patch_instruction(>instr[2], bpinstr); return bp; } } @@