All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexander Graf <agraf@suse.de>
To: kvm@vger.kernel.org
Cc: kvm-ppc@vger.kernel.org, gleb@redhat.com,
	Paolo Bonzini <pbonzini@redhat.com>,
	Paul Mackerras <paulus@samba.org>
Subject: [PULL 09/36] KVM: PPC: Book3S HV: Use load/store_fp_state functions in HV guest entry/exit
Date: Wed, 29 Jan 2014 17:12:48 +0100	[thread overview]
Message-ID: <1391011995-4891-10-git-send-email-agraf@suse.de> (raw)
In-Reply-To: <1391011995-4891-1-git-send-email-agraf@suse.de>

From: Paul Mackerras <paulus@samba.org>

This modifies kvmppc_load_fp and kvmppc_save_fp to use the generic
FP/VSX and VMX load/store functions instead of open-coding the
FP/VSX/VMX load/store instructions.  Since kvmppc_load/save_fp don't
follow C calling conventions, we make them private symbols within
book3s_hv_rmhandlers.S.

Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/powerpc/kernel/asm-offsets.c       |  2 -
 arch/powerpc/kvm/book3s_hv_rmhandlers.S | 86 +++++++++------------------------
 2 files changed, 22 insertions(+), 66 deletions(-)

diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 8403f90..5e64c3d 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -426,10 +426,8 @@ int main(void)
 	DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
 	DEFINE(VCPU_VRSAVE, offsetof(struct kvm_vcpu, arch.vrsave));
 	DEFINE(VCPU_FPRS, offsetof(struct kvm_vcpu, arch.fp.fpr));
-	DEFINE(VCPU_FPSCR, offsetof(struct kvm_vcpu, arch.fp.fpscr));
 #ifdef CONFIG_ALTIVEC
 	DEFINE(VCPU_VRS, offsetof(struct kvm_vcpu, arch.vr.vr));
-	DEFINE(VCPU_VSCR, offsetof(struct kvm_vcpu, arch.vr.vscr));
 #endif
 	DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
 	DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 47fd536..acbd1d6 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -1261,7 +1261,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
 	/* save FP state */
 	mr	r3, r9
-	bl	.kvmppc_save_fp
+	bl	kvmppc_save_fp
 
 	/* Increment yield count if they have a VPA */
 	ld	r8, VCPU_VPA(r9)	/* do they have a VPA? */
@@ -1691,7 +1691,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
 	std	r31, VCPU_GPR(R31)(r3)
 
 	/* save FP state */
-	bl	.kvmppc_save_fp
+	bl	kvmppc_save_fp
 
 	/*
 	 * Take a nap until a decrementer or external interrupt occurs,
@@ -1869,8 +1869,12 @@ kvmppc_read_intr:
 /*
  * Save away FP, VMX and VSX registers.
  * r3 = vcpu pointer
+ * N.B. r30 and r31 are volatile across this function,
+ * thus it is not callable from C.
  */
-_GLOBAL(kvmppc_save_fp)
+kvmppc_save_fp:
+	mflr	r30
+	mr	r31,r3
 	mfmsr	r5
 	ori	r8,r5,MSR_FP
 #ifdef CONFIG_ALTIVEC
@@ -1885,42 +1889,17 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
 #endif
 	mtmsrd	r8
 	isync
-#ifdef CONFIG_VSX
-BEGIN_FTR_SECTION
-	reg = 0
-	.rept	32
-	li	r6,reg*16+VCPU_FPRS
-	STXVD2X(reg,R6,R3)
-	reg = reg + 1
-	.endr
-FTR_SECTION_ELSE
-#endif
-	reg = 0
-	.rept	32
-	stfd	reg,reg*8+VCPU_FPRS(r3)
-	reg = reg + 1
-	.endr
-#ifdef CONFIG_VSX
-ALT_FTR_SECTION_END_IFSET(CPU_FTR_VSX)
-#endif
-	mffs	fr0
-	stfd	fr0,VCPU_FPSCR(r3)
-
+	addi	r3,r3,VCPU_FPRS
+	bl	.store_fp_state
 #ifdef CONFIG_ALTIVEC
 BEGIN_FTR_SECTION
-	reg = 0
-	.rept	32
-	li	r6,reg*16+VCPU_VRS
-	stvx	reg,r6,r3
-	reg = reg + 1
-	.endr
-	mfvscr	vr0
-	li	r6,VCPU_VSCR
-	stvx	vr0,r6,r3
+	addi	r3,r31,VCPU_VRS
+	bl	.store_vr_state
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif
 	mfspr	r6,SPRN_VRSAVE
 	stw	r6,VCPU_VRSAVE(r3)
+	mtlr	r30
 	mtmsrd	r5
 	isync
 	blr
@@ -1928,9 +1907,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 /*
  * Load up FP, VMX and VSX registers
  * r4 = vcpu pointer
+ * N.B. r30 and r31 are volatile across this function,
+ * thus it is not callable from C.
  */
-	.globl	kvmppc_load_fp
 kvmppc_load_fp:
+	mflr	r30
+	mr	r31,r4
 	mfmsr	r9
 	ori	r8,r9,MSR_FP
 #ifdef CONFIG_ALTIVEC
@@ -1945,42 +1927,18 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
 #endif
 	mtmsrd	r8
 	isync
-	lfd	fr0,VCPU_FPSCR(r4)
-	MTFSF_L(fr0)
-#ifdef CONFIG_VSX
-BEGIN_FTR_SECTION
-	reg = 0
-	.rept	32
-	li	r7,reg*16+VCPU_FPRS
-	LXVD2X(reg,R7,R4)
-	reg = reg + 1
-	.endr
-FTR_SECTION_ELSE
-#endif
-	reg = 0
-	.rept	32
-	lfd	reg,reg*8+VCPU_FPRS(r4)
-	reg = reg + 1
-	.endr
-#ifdef CONFIG_VSX
-ALT_FTR_SECTION_END_IFSET(CPU_FTR_VSX)
-#endif
-
+	addi	r3,r4,VCPU_FPRS
+	bl	.load_fp_state
 #ifdef CONFIG_ALTIVEC
 BEGIN_FTR_SECTION
-	li	r7,VCPU_VSCR
-	lvx	vr0,r7,r4
-	mtvscr	vr0
-	reg = 0
-	.rept	32
-	li	r7,reg*16+VCPU_VRS
-	lvx	reg,r7,r4
-	reg = reg + 1
-	.endr
+	addi	r3,r31,VCPU_VRS
+	bl	.load_vr_state
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif
 	lwz	r7,VCPU_VRSAVE(r4)
 	mtspr	SPRN_VRSAVE,r7
+	mtlr	r30
+	mr	r4,r31
 	blr
 
 /*
-- 
1.8.1.4

WARNING: multiple messages have this Message-ID (diff)
From: Alexander Graf <agraf@suse.de>
To: kvm@vger.kernel.org
Cc: kvm-ppc@vger.kernel.org, gleb@redhat.com,
	Paolo Bonzini <pbonzini@redhat.com>,
	Paul Mackerras <paulus@samba.org>
Subject: [PULL 09/36] KVM: PPC: Book3S HV: Use load/store_fp_state functions in HV guest entry/exit
Date: Wed, 29 Jan 2014 16:12:48 +0000	[thread overview]
Message-ID: <1391011995-4891-10-git-send-email-agraf@suse.de> (raw)
In-Reply-To: <1391011995-4891-1-git-send-email-agraf@suse.de>

From: Paul Mackerras <paulus@samba.org>

This modifies kvmppc_load_fp and kvmppc_save_fp to use the generic
FP/VSX and VMX load/store functions instead of open-coding the
FP/VSX/VMX load/store instructions.  Since kvmppc_load/save_fp don't
follow C calling conventions, we make them private symbols within
book3s_hv_rmhandlers.S.

Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/powerpc/kernel/asm-offsets.c       |  2 -
 arch/powerpc/kvm/book3s_hv_rmhandlers.S | 86 +++++++++------------------------
 2 files changed, 22 insertions(+), 66 deletions(-)

diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 8403f90..5e64c3d 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -426,10 +426,8 @@ int main(void)
 	DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
 	DEFINE(VCPU_VRSAVE, offsetof(struct kvm_vcpu, arch.vrsave));
 	DEFINE(VCPU_FPRS, offsetof(struct kvm_vcpu, arch.fp.fpr));
-	DEFINE(VCPU_FPSCR, offsetof(struct kvm_vcpu, arch.fp.fpscr));
 #ifdef CONFIG_ALTIVEC
 	DEFINE(VCPU_VRS, offsetof(struct kvm_vcpu, arch.vr.vr));
-	DEFINE(VCPU_VSCR, offsetof(struct kvm_vcpu, arch.vr.vscr));
 #endif
 	DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
 	DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 47fd536..acbd1d6 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -1261,7 +1261,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
 	/* save FP state */
 	mr	r3, r9
-	bl	.kvmppc_save_fp
+	bl	kvmppc_save_fp
 
 	/* Increment yield count if they have a VPA */
 	ld	r8, VCPU_VPA(r9)	/* do they have a VPA? */
@@ -1691,7 +1691,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
 	std	r31, VCPU_GPR(R31)(r3)
 
 	/* save FP state */
-	bl	.kvmppc_save_fp
+	bl	kvmppc_save_fp
 
 	/*
 	 * Take a nap until a decrementer or external interrupt occurs,
@@ -1869,8 +1869,12 @@ kvmppc_read_intr:
 /*
  * Save away FP, VMX and VSX registers.
  * r3 = vcpu pointer
+ * N.B. r30 and r31 are volatile across this function,
+ * thus it is not callable from C.
  */
-_GLOBAL(kvmppc_save_fp)
+kvmppc_save_fp:
+	mflr	r30
+	mr	r31,r3
 	mfmsr	r5
 	ori	r8,r5,MSR_FP
 #ifdef CONFIG_ALTIVEC
@@ -1885,42 +1889,17 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
 #endif
 	mtmsrd	r8
 	isync
-#ifdef CONFIG_VSX
-BEGIN_FTR_SECTION
-	reg = 0
-	.rept	32
-	li	r6,reg*16+VCPU_FPRS
-	STXVD2X(reg,R6,R3)
-	reg = reg + 1
-	.endr
-FTR_SECTION_ELSE
-#endif
-	reg = 0
-	.rept	32
-	stfd	reg,reg*8+VCPU_FPRS(r3)
-	reg = reg + 1
-	.endr
-#ifdef CONFIG_VSX
-ALT_FTR_SECTION_END_IFSET(CPU_FTR_VSX)
-#endif
-	mffs	fr0
-	stfd	fr0,VCPU_FPSCR(r3)
-
+	addi	r3,r3,VCPU_FPRS
+	bl	.store_fp_state
 #ifdef CONFIG_ALTIVEC
 BEGIN_FTR_SECTION
-	reg = 0
-	.rept	32
-	li	r6,reg*16+VCPU_VRS
-	stvx	reg,r6,r3
-	reg = reg + 1
-	.endr
-	mfvscr	vr0
-	li	r6,VCPU_VSCR
-	stvx	vr0,r6,r3
+	addi	r3,r31,VCPU_VRS
+	bl	.store_vr_state
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif
 	mfspr	r6,SPRN_VRSAVE
 	stw	r6,VCPU_VRSAVE(r3)
+	mtlr	r30
 	mtmsrd	r5
 	isync
 	blr
@@ -1928,9 +1907,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 /*
  * Load up FP, VMX and VSX registers
  * r4 = vcpu pointer
+ * N.B. r30 and r31 are volatile across this function,
+ * thus it is not callable from C.
  */
-	.globl	kvmppc_load_fp
 kvmppc_load_fp:
+	mflr	r30
+	mr	r31,r4
 	mfmsr	r9
 	ori	r8,r9,MSR_FP
 #ifdef CONFIG_ALTIVEC
@@ -1945,42 +1927,18 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
 #endif
 	mtmsrd	r8
 	isync
-	lfd	fr0,VCPU_FPSCR(r4)
-	MTFSF_L(fr0)
-#ifdef CONFIG_VSX
-BEGIN_FTR_SECTION
-	reg = 0
-	.rept	32
-	li	r7,reg*16+VCPU_FPRS
-	LXVD2X(reg,R7,R4)
-	reg = reg + 1
-	.endr
-FTR_SECTION_ELSE
-#endif
-	reg = 0
-	.rept	32
-	lfd	reg,reg*8+VCPU_FPRS(r4)
-	reg = reg + 1
-	.endr
-#ifdef CONFIG_VSX
-ALT_FTR_SECTION_END_IFSET(CPU_FTR_VSX)
-#endif
-
+	addi	r3,r4,VCPU_FPRS
+	bl	.load_fp_state
 #ifdef CONFIG_ALTIVEC
 BEGIN_FTR_SECTION
-	li	r7,VCPU_VSCR
-	lvx	vr0,r7,r4
-	mtvscr	vr0
-	reg = 0
-	.rept	32
-	li	r7,reg*16+VCPU_VRS
-	lvx	reg,r7,r4
-	reg = reg + 1
-	.endr
+	addi	r3,r31,VCPU_VRS
+	bl	.load_vr_state
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif
 	lwz	r7,VCPU_VRSAVE(r4)
 	mtspr	SPRN_VRSAVE,r7
+	mtlr	r30
+	mr	r4,r31
 	blr
 
 /*
-- 
1.8.1.4


  parent reply	other threads:[~2014-01-29 16:12 UTC|newest]

Thread overview: 76+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-29 16:12 [PULL 00/36] ppc patch queue 2014-01-29 Alexander Graf
2014-01-29 16:12 ` Alexander Graf
2014-01-29 16:12 ` [PULL 01/36] powerpc: kvm: optimize "sc 1" as fast return Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` [PULL 02/36] KVM: PPC: Add devname:kvm aliases for modules Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` [PULL 03/36] KVM: PPC: fix couple of memory leaks in MPIC/XICS devices Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` [PULL 04/36] kvm/powerpc: rename kvm_hypercall() to epapr_hypercall() Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` [PULL 05/36] kvm/powerpc: move kvm_hypercall0() and friends to epapr_hypercall0() Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` [PULL 06/36] KVM: PPC: Use load_fp/vr_state rather than load_up_fpu/altivec Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` [PULL 07/36] KVM: PPC: Store FP/VSX/VMX state in thread_fp/vr_state structures Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` [PULL 08/36] KVM: PPC: Load/save FP/VMX/VSX state directly to/from vcpu struct Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` Alexander Graf [this message]
2014-01-29 16:12   ` [PULL 09/36] KVM: PPC: Book3S HV: Use load/store_fp_state functions in HV guest entry/exit Alexander Graf
2014-01-29 16:12 ` [PULL 10/36] kvm: booke: clear host tlb reference flag on guest tlb invalidation Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` [PULL 11/36] kvm: book3s: rename lookup_linux_pte() to lookup_linux_pte_and_update() Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` [PULL 12/36] kvm: powerpc: define a linux pte lookup function Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` [PULL 13/36] kvm: powerpc: use caching attributes as per linux pte Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` [PULL 14/36] KVM: PPC: Book3E HV: call RECONCILE_IRQ_STATE to sync the software state Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` [PULL 15/36] KVM: PPC: NULL return of kvmppc_mmu_hpte_cache_next should be handled Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` [PULL 16/36] KVM: PPC: Unify kvmppc_get_last_inst and sc Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` [PULL 17/36] KVM: PPC: Book3S: MMIO emulation support for little endian guests Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` [PULL 18/36] KVM: PPC: Book3S HV: use xics_wake_cpu only when defined Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` [PULL 19/36] KVM: PPC: e500: Fix bad address type in deliver_tlb_misss() Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:12 ` [PULL 20/36] kvm/ppc: IRQ disabling cleanup Alexander Graf
2014-01-29 16:12   ` Alexander Graf
2014-01-29 16:13 ` [PULL 21/36] KVM: PPC: Book3S HV: Don't set DABR on POWER8 Alexander Graf
2014-01-29 16:13   ` Alexander Graf
2014-01-29 16:13 ` [PULL 22/36] KVM: PPC: Book3S HV: Align physical and virtual CPU thread numbers Alexander Graf
2014-01-29 16:13   ` Alexander Graf
2014-01-29 16:13 ` [PULL 23/36] KVM: PPC: Book3S HV: Context-switch new POWER8 SPRs Alexander Graf
2014-01-29 16:13   ` Alexander Graf
2014-01-29 16:13 ` [PULL 24/36] KVM: PPC: Book3S HV: Flush the correct number of TLB sets on POWER8 Alexander Graf
2014-01-29 16:13   ` Alexander Graf
2014-01-29 16:13 ` [PULL 25/36] KVM: PPC: Book3S HV: Add handler for HV facility unavailable Alexander Graf
2014-01-29 16:13   ` Alexander Graf
2014-01-29 16:13 ` [PULL 26/36] KVM: PPC: Book3S HV: Implement architecture compatibility modes for POWER8 Alexander Graf
2014-01-29 16:13   ` Alexander Graf
2014-01-29 16:13 ` [PULL 27/36] KVM: PPC: Book3S HV: Consolidate code that checks reason for wake from nap Alexander Graf
2014-01-29 16:13   ` Alexander Graf
2014-01-29 16:13 ` [PULL 28/36] KVM: PPC: Book3S HV: Handle guest using doorbells for IPIs Alexander Graf
2014-01-29 16:13   ` Alexander Graf
2014-01-29 16:13 ` [PULL 29/36] KVM: PPC: Book3S HV: Handle new LPCR bits on POWER8 Alexander Graf
2014-01-29 16:13   ` Alexander Graf
2014-01-29 16:13 ` [PULL 30/36] KVM: PPC: Book3S HV: Prepare for host using hypervisor doorbells Alexander Graf
2014-01-29 16:13   ` Alexander Graf
2014-01-29 16:13 ` [PULL 31/36] KVM: PPC: Book3S HV: Add support for DABRX register on POWER7 Alexander Graf
2014-01-29 16:13   ` Alexander Graf
2014-01-29 16:13 ` [PULL 32/36] KVM: PPC: Book3S HV: Basic little-endian guest support Alexander Graf
2014-01-29 16:13   ` Alexander Graf
2014-01-29 16:13 ` [PULL 33/36] powerpc/Kconfig: Make TM select VSX and VMX Alexander Graf
2014-01-29 16:13   ` Alexander Graf
2014-01-29 16:13 ` [PULL 34/36] KVM: PPC: Book3S HV: Add new state for transactional memory Alexander Graf
2014-01-29 16:13   ` Alexander Graf
2014-01-29 16:13 ` [PULL 35/36] KVM: PPC: Book3S HV: Add software abort codes " Alexander Graf
2014-01-29 16:13   ` Alexander Graf
2014-01-29 16:13 ` [PULL 36/36] KVM: PPC: Book3S PR: Cope with doorbell interrupts Alexander Graf
2014-01-29 16:13   ` Alexander Graf
2014-01-29 17:31 ` [PULL 00/36] ppc patch queue 2014-01-29 Paolo Bonzini
2014-01-29 17:31   ` Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1391011995-4891-10-git-send-email-agraf@suse.de \
    --to=agraf@suse.de \
    --cc=gleb@redhat.com \
    --cc=kvm-ppc@vger.kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=paulus@samba.org \
    --cc=pbonzini@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.