From: Scott Wood <hidden> Date: 2015-10-07 03:48:37
This allows SMP kernels to work as kdump crash kernels. While crash
kernels don't really need to be SMP, this prevents things from breaking
if a user does it anyway (which is not something you want to only find
out once the main kernel has crashed in the field, especially if
whether it works or not depends on which cpu crashed).
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/platforms/85xx/smp.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
@@ -173,15 +173,22 @@ static inline u32 read_spin_table_addr_l(void *spin_table)staticvoidwake_hw_thread(void*info){voidfsl_secondary_thread_init(void);-unsignedlongimsr1,inia1;+unsignedlongimsr,inia;intnr=*(constint*)info;-imsr1=MSR_KERNEL;-inia1=*(unsignedlong*)fsl_secondary_thread_init;--mttmr(TMRN_IMSR1,imsr1);-mttmr(TMRN_INIA1,inia1);-mtspr(SPRN_TENS,TEN_THREAD(1));+imsr=MSR_KERNEL;+inia=*(unsignedlong*)fsl_secondary_thread_init;++if(cpu_thread_in_core(nr)==0){+/* For when we boot on a secondary thread with kdump */+mttmr(TMRN_IMSR0,imsr);+mttmr(TMRN_INIA0,inia);+mtspr(SPRN_TENS,TEN_THREAD(0));+}else{+mttmr(TMRN_IMSR1,imsr);+mttmr(TMRN_INIA1,inia);+mtspr(SPRN_TENS,TEN_THREAD(1));+}smp_generic_kick_cpu(nr);}
@@ -224,6 +231,12 @@ static int smp_85xx_kick_cpu(int nr)smp_call_function_single(primary,wake_hw_thread,&nr,0);return0;+}elseif(cpu_thread_in_core(boot_cpuid)!=0&&+cpu_first_thread_sibling(boot_cpuid)==nr){+if(WARN_ON_ONCE(!cpu_has_feature(CPU_FTR_SMT)))+return-ENOENT;++smp_call_function_single(boot_cpuid,wake_hw_thread,&nr,0);}#endif
From: Scott Wood <hidden> Date: 2015-10-07 03:48:37
Problems have been observed in coreint (EPR) mode if interrupts are
left pending (due to the lack of device quiescence with kdump) after
having tried to deliver to a CPU but unable to deliver due to MSR[EE]
-- interrupts no longer get reliably delivered in the new kernel. I
tried various ways of fixing it up inside the crash kernel itself, and
none worked (including resetting the entire mpic). Masking all
interrupts and issuing EOIs in the crashing kernel did help a lot of
the time, but the behavior was not consistent.
Thus, stick to standard IACK mode when kdump is a possibility.
Signed-off-by: Scott Wood <redacted>
---
Previously I discussed the possibility of removing coreint entirely,
but I think we want to keep it for virtualized guests.
---
arch/powerpc/platforms/85xx/corenet_generic.c | 4 ++++
1 file changed, 4 insertions(+)
From: Scott Wood <hidden> Date: 2015-10-07 03:48:38
85xx currently uses the generic timebase sync mechanism when
CONFIG_KEXEC is enabled, because 32-bit 85xx kexec support does a hard
reset of each core. 64-bit 85xx kexec does not do this, so we neither
need nor want this (nor is the generic timebase sync code built on
ppc64).
FWIW, I don't like the fact that the hard reset is done on 32-bit
kexec, and I especially don't like the timebase sync being triggered
only on the presence of CONFIG_KEXEC rather than actually booting in
that environment, but that's beyond the scope of this patch...
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/platforms/85xx/smp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: Scott Wood <hidden> Date: 2015-10-07 03:48:40
Otherwise, because the top end of the crash kernel is treated as the
absolute top of memory rather than the beginning of a reserved region,
in-flight DMA from the previous kernel that targets areas above the
crash kernel can trigger a storm of PCI errors. We only do this for
kdump, not normal kexec, in case kexec is being used to upgrade to a
kernel that wants a different inbound memory map.
Signed-off-by: Scott Wood <redacted>
Cc: Mingkai Hu <redacted>
---
v2: new patch
arch/powerpc/sysdev/fsl_pci.c | 84 +++++++++++++++++++++++++++++++------------
1 file changed, 61 insertions(+), 23 deletions(-)
@@ -204,8 +227,11 @@ static void setup_pci_atmu(struct pci_controller *hose)/* Disable all windows (except powar0 since it's ignored) */for(i=1;i<5;i++)out_be32(&pci->pow[i].powar,0);-for(i=start_idx;i<end_idx;i++)-out_be32(&pci->piw[i].piwar,0);++if(setup_inbound){+for(i=start_idx;i<end_idx;i++)+out_be32(&pci->piw[i].piwar,0);+}/* Setup outbound MEM window */for(i=0,j=1;i<3;i++){
@@ -278,6 +304,7 @@ static void setup_pci_atmu(struct pci_controller *hose)/* Setup inbound mem window */mem=memblock_end_of_DRAM();+pr_info("%s: end of DRAM %llx\n",__func__,mem);/**Themsi-address-64property,ifitexists,indicatesthephysical
From: Scott Wood <hidden> Date: 2015-10-07 03:48:41
Use an AS=1 trampoline TLB entry to allow all normal TLB1 entries to
be loaded at once. This avoids the need to keep the translation that
code is executing from in the same TLB entry in the final TLB
configuration as during early boot, which in turn is helpful for
relocatable kernels (e.g. kdump) where the kernel is not running from
what would be the first TLB entry.
On e6500, we limit map_mem_in_cams() to the primary hwthread of a
core (the boot cpu is always considered primary, as a kdump kernel
can be entered on any cpu). Each TLB only needs to be set up once,
and when we do, we don't want another thread to be running when we
create a temporary trampoline TLB1 entry.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/kernel/setup_64.c | 8 +++++
arch/powerpc/mm/fsl_booke_mmu.c | 15 ++++++++--
arch/powerpc/mm/mmu_decl.h | 1 +
arch/powerpc/mm/tlb_nohash.c | 19 +++++++++++-
arch/powerpc/mm/tlb_nohash_low.S | 63 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 102 insertions(+), 4 deletions(-)
@@ -628,10 +629,26 @@ static void early_init_this_mmu(void)#ifdef CONFIG_PPC_FSL_BOOK3Eif(mmu_has_feature(MMU_FTR_TYPE_FSL_E)){unsignedintnum_cams;+int__maybe_unusedcpu=smp_processor_id();+boolmap=true;/* use a quarter of the TLBCAM for bolted linear map */num_cams=(mfspr(SPRN_TLB1CFG)&TLBnCFG_N_ENTRY)/4;-linear_map_top=map_mem_in_cams(linear_map_top,num_cams);++/*+*Onlydothemappingoncepercore,orelsethe+*transientmappingwouldcauseproblems.+*/+#ifdef CONFIG_SMP+if(cpu!=boot_cpuid&&+(cpu!=cpu_first_thread_sibling(cpu)||+cpu==cpu_first_thread_sibling(boot_cpuid)))+map=false;+#endif++if(map)+linear_map_top=map_mem_in_cams(linear_map_top,+num_cams);}#endif
@@ -423,4 +424,66 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS)tlbweisyncblr++/*+*LoadmultipleTLBentriesatonce,usinganalternate-space+*trampolinesothatwedon't have to care about whether the same+*TLBentrymapsusbeforeandafter.+*+*r3=firstentrytowrite+*r4=numberofentriestowrite+*r5=temporarytlbentry+*/+_GLOBAL(loadcam_multi)+mflrr8++/*+*SetuptemporaryTLBentrythatisthesameaswhatwe're+*runningfrom,butinAS=1.+*/+bl1f+1:mflrr6+tlbsx0,r8+mfsprr6,SPRN_MAS1+orir6,r6,MAS1_TS+mtsprSPRN_MAS1,r6+mfsprr6,SPRN_MAS0+rlwimir6,r5,MAS0_ESEL_SHIFT,MAS0_ESEL_MASK+mrr7,r5+mtsprSPRN_MAS0,r6+isync+tlbwe+isync++/*SwitchtoAS=1*/+mfmsrr6+orir6,r6,MSR_IS|MSR_DS+mtmsrr6+isync++mrr9,r3+addr10,r3,r4+2:blloadcam_entry+addir9,r9,1+cmpwr9,r10+mrr3,r9+blt2b++/*ReturntoAS=0andclearthetemporaryentry*/+mfmsrr6+rlwinm.r6,r6,0,~(MSR_IS|MSR_DS)+mtmsrr6+isync++lir6,0+mtsprSPRN_MAS1,r6+rlwinmr6,r7,MAS0_ESEL_SHIFT,MAS0_ESEL_MASK+orisr6,r6,MAS0_TLBSEL(1)@h+mtsprSPRN_MAS0,r6+isync+tlbwe+isync++mtlrr8+blr#endif
From: Scott Wood <hidden> Date: 2015-10-07 03:48:42
This is required for kdump to work when loaded at at an address that
does not fall within the first TLB entry -- which can easily happen
because while the lower limit is enforced via reserved memory, which
doesn't affect how much is mapped, the upper limit is enforced via a
different mechanism that does. Thus, more TLB entries are needed than
would normally be used, as the total memory to be mapped might not be a
power of two.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/mm/fsl_booke_mmu.c | 22 +++++++++++++++-------
arch/powerpc/mm/mmu_decl.h | 3 ++-
arch/powerpc/mm/tlb_nohash.c | 24 +++++++++++++++++-------
3 files changed, 34 insertions(+), 15 deletions(-)
@@ -178,7 +178,8 @@ unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,}staticunsignedlongmap_mem_in_cams_addr(phys_addr_tphys,unsignedlongvirt,-unsignedlongram,intmax_cam_idx)+unsignedlongram,intmax_cam_idx,+booldryrun){inti;unsignedlongamount_mapped=0;
@@ -188,7 +189,9 @@ static unsigned long map_mem_in_cams_addr(phys_addr_t phys, unsigned long virt,unsignedlongcam_sz;cam_sz=calc_cam_sz(ram,virt,phys);-preptlbcam(i,virt,phys,cam_sz,pgprot_val(PAGE_KERNEL_X),0);+if(!dryrun)+preptlbcam(i,virt,phys,cam_sz,+pgprot_val(PAGE_KERNEL_X),0);ram-=cam_sz;amount_mapped+=cam_sz;
@@ -196,6 +199,9 @@ static unsigned long map_mem_in_cams_addr(phys_addr_t phys, unsigned long virt,phys+=cam_sz;}+if(dryrun)+returnamount_mapped;+loadcam_multi(0,i,max_cam_idx);tlbcam_index=i;
@@ -208,12 +214,12 @@ static unsigned long map_mem_in_cams_addr(phys_addr_t phys, unsigned long virt,returnamount_mapped;}-unsignedlongmap_mem_in_cams(unsignedlongram,intmax_cam_idx)+unsignedlongmap_mem_in_cams(unsignedlongram,intmax_cam_idx,booldryrun){unsignedlongvirt=PAGE_OFFSET;phys_addr_tphys=memstart_addr;-returnmap_mem_in_cams_addr(phys,virt,ram,max_cam_idx);+returnmap_mem_in_cams_addr(phys,virt,ram,max_cam_idx,dryrun);}#ifdef CONFIG_PPC32
@@ -312,10 +318,12 @@ notrace void __init relocate_init(u64 dt_ptr, phys_addr_t start)n=switch_to_as1();/* map a 64M area for the second relocation */if(memstart_addr>start)-map_mem_in_cams(0x4000000,CONFIG_LOWMEM_CAM_NUM);+map_mem_in_cams(0x4000000,CONFIG_LOWMEM_CAM_NUM,+false);elsemap_mem_in_cams_addr(start,PAGE_OFFSET+offset,-0x4000000,CONFIG_LOWMEM_CAM_NUM);+0x4000000,CONFIG_LOWMEM_CAM_NUM,+false);restore_to_as0(n,offset,__va(dt_ptr),1);/* We should never reach here */panic("Relocation error");
@@ -757,8 +761,14 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base,#ifdef CONFIG_PPC_FSL_BOOK3Eif(mmu_has_feature(MMU_FTR_TYPE_FSL_E)){unsignedlonglinear_sz;-linear_sz=calc_cam_sz(first_memblock_size,PAGE_OFFSET,-first_memblock_base);+unsignedintnum_cams;++/* use a quarter of the TLBCAM for bolted linear map */+num_cams=(mfspr(SPRN_TLB1CFG)&TLBnCFG_N_ENTRY)/4;++linear_sz=map_mem_in_cams(first_memblock_size,num_cams,+true);+ppc64_rma_size=min_t(u64,linear_sz,0x40000000);}else#endif
From: Scott Wood <hidden> Date: 2015-10-07 03:48:47
The new kernel will be expecting secondary threads to be disabled,
not spinning.
Signed-off-by: Scott Wood <redacted>
---
v2: minor cleanup
arch/powerpc/kernel/head_64.S | 16 ++++++++++++++
arch/powerpc/platforms/85xx/smp.c | 46 +++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+)
@@ -196,10 +198,24 @@ _GLOBAL(fsl_secondary_thread_init)*number.Therearetwothreadspercore,soshifteverything*butthelowbitrightbytwobitssothatthecpunumberingis*continuous.+*+*IftheoldvalueofBUCSRisnon-zero,thisthreadhasrun+*before.Thus,weassumewearecomingfromkexecorasimilar+*scenario,andPIRisalreadysettothecorrectvalue.This+*isabitofahack,buttherearelimitedopportunitiesfor+*gettinginformationintothethreadandthealternatives+*seemedlikethey'd be overkill. We can'ttelljustbylooking+*attheoldPIRvaluewhichstateit's in, since the same value+*couldbevalidforonethreadoutofresetandforadifferent+*threadinLinux.*/+mfsprr3,SPRN_PIR+cmpwir4,0+bne1frlwimir3,r3,30,2,30mtsprSPRN_PIR,r3+1:#endif _GLOBAL(generic_secondary_thread_init)
@@ -374,9 +374,55 @@ static void mpc85xx_smp_kexec_down(void *arg)#elsevoidmpc85xx_smp_kexec_cpu_down(intcrash_shutdown,intsecondary){+intcpu=smp_processor_id();+intsibling=cpu_last_thread_sibling(cpu);+boolnotified=false;+intdisable_cpu;+intdisable_threadbit=0;+longstart=mftb();+longnow;+local_irq_disable();hard_irq_disable();mpic_teardown_this_cpu(secondary);++if(cpu==crashing_cpu&&cpu_thread_in_core(cpu)!=0){+/*+*Weenterthecrashkernelonwhatevercpucrashed,+*evenifit'sasecondarythread.Ifthat'sthecase,+*disablethecorrespondingprimarythread.+*/+disable_threadbit=1;+disable_cpu=cpu_first_thread_sibling(cpu);+}elseif(sibling!=crashing_cpu&&+cpu_thread_in_core(cpu)==0&&+cpu_thread_in_core(sibling)!=0){+disable_threadbit=2;+disable_cpu=sibling;+}++if(disable_threadbit){+while(paca[disable_cpu].kexec_state<KEXEC_STATE_REAL_MODE){+barrier();+now=mftb();+if(!notified&&now-start>1000000){+pr_info("%s/%d: waiting for cpu %d to enter KEXEC_STATE_REAL_MODE (%d)\n",+__func__,smp_processor_id(),+disable_cpu,+paca[disable_cpu].kexec_state);+notified=true;+}+}++if(notified){+pr_info("%s: cpu %d done waiting\n",+__func__,disable_cpu);+}++mtspr(SPRN_TENC,disable_threadbit);+while(mfspr(SPRN_TENSR)&disable_threadbit)+cpu_relax();+}}#endif
From: Scott Wood <hidden> Date: 2015-10-07 03:48:49
From: Tiejun Chen <redacted>
Rename 'interrupt_end_book3e' to '__end_interrupts' so that the symbol
can be used by both book3s and book3e.
Signed-off-by: Tiejun Chen <redacted>
[scottwood: edit changelog]
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/kernel/exceptions-64e.S | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
From: Scott Wood <hidden> Date: 2015-10-07 03:48:50
From: Tiejun Chen <redacted>
Convert r4/r5, not r6, to a virtual address when calling
copy_and_flush. Otherwise, r3 is already virtual, and copy_to_flush
tries to access r3+r6, PAGE_OFFSET gets added twice.
This isn't normally seen because on book3e we normally enter with
the kernel at zero and thus skip copy_to_flush -- but it will be
needed for kexec support.
Signed-off-by: Tiejun Chen <redacted>
[scottwood: split patch and rewrote changelog]
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/kernel/head_64.S | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
From: Scott Wood <hidden> Date: 2015-10-07 03:48:53
From: Tiejun Chen <redacted>
book3e is different with book3s since 3s includes the exception
vectors code in head_64.S as it relies on absolute addressing
which is only possible within this compilation unit. So we have
to get that label address with got.
And when boot a relocated kernel, we should reset ipvr properly again
after .relocate.
Signed-off-by: Tiejun Chen <redacted>
[scottwood: cleanup and ifdef removal]
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/include/asm/exception-64e.h | 4 ++--
arch/powerpc/kernel/exceptions-64e.S | 9 +++++++--
arch/powerpc/kernel/head_64.S | 22 +++++++++++++++++++---
3 files changed, 28 insertions(+), 7 deletions(-)
From: Scott Wood <hidden> Date: 2015-10-07 03:48:54
While book3e doesn't have "real mode", we still want to wait for
all the non-crash cpus to complete their shutdown.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/kernel/crash.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
@@ -221,8 +221,8 @@ void crash_kexec_secondary(struct pt_regs *regs)#endif /* CONFIG_SMP *//* wait for all the CPUs to hit real mode but timeout if they don't come in */-#if defined(CONFIG_SMP) && defined(CONFIG_PPC_STD_MMU_64)-staticvoidcrash_kexec_wait_realmode(intcpu)+#if defined(CONFIG_SMP) && defined(CONFIG_PPC64)+staticvoid__maybe_unusedcrash_kexec_wait_realmode(intcpu){unsignedintmsecs;inti;
From: Scott Wood <hidden> Date: 2015-10-07 03:48:55
This limit only makes sense on book3s, and on book3e it can cause
problems with kdump if we don't have any memory under 256 MiB.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/kernel/paca.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
From: Scott Wood <hidden> Date: 2015-10-07 03:48:58
From: Tiejun Chen <redacted>
book3e has no real MMU mode so we have to create an identity TLB
mapping to make sure we can access the real physical address.
Signed-off-by: Tiejun Chen <redacted>
[scottwood: cleanup, and split off some changes]
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/kernel/misc_64.S | 52 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 51 insertions(+), 1 deletion(-)
@@ -525,6 +571,10 @@ _GLOBAL(kexec_smp_wait)*don't overwrite r3 here, it is live for kexec_wait above.*/real_mode:/*assumenormalblrreturn*/+#ifdef CONFIG_PPC_BOOK3E+/*Createanidentitymapping.*/+bkexec_create_tlb+#else1:lir9,MSR_RIlir10,MSR_DR|MSR_IRmflrr11/*returnaddresstoSRR0*/
From: Scott Wood <hidden> Date: 2015-10-07 03:49:01
The way VIRT_PHYS_OFFSET is not correct on book3e-64, because
it does not account for CONFIG_RELOCATABLE other than via the
32-bit-only virt_phys_offset.
book3e-64 can (and if the comment about a GCC miscompilation is still
relevant, should) use the normal ppc64 __va/__pa.
At this point, only booke-32 will use VIRT_PHYS_OFFSET, so given the
issues with its calculation, restrict its definition to booke-32.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/include/asm/page.h | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
From: Scott Wood <hidden> Date: 2015-10-07 03:49:02
book3e_secondary_core_init will only create a TLB entry if r4 = 0,
so do so.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/kernel/misc_64.S | 2 ++
1 file changed, 2 insertions(+)
@@ -365,6 +381,7 @@ void default_machine_kexec(struct kimage *image)/* NOTREACHED */}+#ifndef CONFIG_PPC_BOOK3E/* Values we need to export to the second kernel via the device tree. */staticunsignedlonghtab_base;staticunsignedlonghtab_size;
Use an AS=1 trampoline TLB entry to allow all normal TLB1 entries to
be loaded at once. This avoids the need to keep the translation that
code is executing from in the same TLB entry in the final TLB
configuration as during early boot, which in turn is helpful for
relocatable kernels (e.g. kdump) where the kernel is not running from
what would be the first TLB entry.
On e6500, we limit map_mem_in_cams() to the primary hwthread of a
core (the boot cpu is always considered primary, as a kdump kernel
can be entered on any cpu). Each TLB only needs to be set up once,
and when we do, we don't want another thread to be running when we
create a temporary trampoline TLB1 entry.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/kernel/setup_64.c | 8 +++++
arch/powerpc/mm/fsl_booke_mmu.c | 15 ++++++++--
arch/powerpc/mm/mmu_decl.h | 1 +
arch/powerpc/mm/tlb_nohash.c | 19 +++++++++++-
arch/powerpc/mm/tlb_nohash_low.S | 63 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 102 insertions(+), 4 deletions(-)
From: Scott Wood <hidden> Date: 2015-10-07 19:58:03
On Wed, 2015-10-07 at 17:00 +0300, Laurentiu Tudor wrote:
On 10/07/2015 06:48 AM, Scott Wood wrote:
quoted
Use an AS=1 trampoline TLB entry to allow all normal TLB1 entries to
be loaded at once. This avoids the need to keep the translation that
code is executing from in the same TLB entry in the final TLB
configuration as during early boot, which in turn is helpful for
relocatable kernels (e.g. kdump) where the kernel is not running from
what would be the first TLB entry.
On e6500, we limit map_mem_in_cams() to the primary hwthread of a
core (the boot cpu is always considered primary, as a kdump kernel
can be entered on any cpu). Each TLB only needs to be set up once,
and when we do, we don't want another thread to be running when we
create a temporary trampoline TLB1 entry.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/kernel/setup_64.c | 8 +++++
arch/powerpc/mm/fsl_booke_mmu.c | 15 ++++++++--
arch/powerpc/mm/mmu_decl.h | 1 +
arch/powerpc/mm/tlb_nohash.c | 19 +++++++++++-
arch/powerpc/mm/tlb_nohash_low.S | 63
++++++++++++++++++++++++++++++++++++++++
5 files changed, 102 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kernel/setup_64.c
b/arch/powerpc/kernel/setup_64.c
index bdcbb71..505ec2c 100644
From: Scott Wood <hidden> Date: 2015-10-19 22:10:34
This limit only makes sense on book3s, and on book3e it can cause
problems with kdump if we don't have any memory under 256 MiB.
Signed-off-by: Scott Wood <redacted>
---
v3: Fix book3s build error
arch/powerpc/kernel/paca.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)