svn commit: r459822 - in head/emulators/xen-kernel: . files

Roger Pau Monné royger at FreeBSD.org
Wed Jan 24 08:51:38 UTC 2018


Author: royger (src committer)
Date: Wed Jan 24 08:51:37 2018
New Revision: 459822
URL: https://svnweb.freebsd.org/changeset/ports/459822

Log:
  xen-kernel: add prerequisites for XSA-254 bandaid
  
  MFH with:	r459787
  MFH:		2018Q1

Added:
  head/emulators/xen-kernel/files/0001-x86-entry-Remove-support-for-partial-cpu_user_regs-f.patch   (contents, props changed)
  head/emulators/xen-kernel/files/0001-x86-mm-Always-set-_PAGE_ACCESSED-on-L4e-updates.patch   (contents, props changed)
Modified:
  head/emulators/xen-kernel/Makefile

Modified: head/emulators/xen-kernel/Makefile
==============================================================================
--- head/emulators/xen-kernel/Makefile	Wed Jan 24 08:49:48 2018	(r459821)
+++ head/emulators/xen-kernel/Makefile	Wed Jan 24 08:51:37 2018	(r459822)
@@ -2,7 +2,7 @@
 
 PORTNAME=	xen
 PORTVERSION=	4.7.2
-PORTREVISION=	8
+PORTREVISION=	9
 CATEGORIES=	emulators
 MASTER_SITES=	http://downloads.xenproject.org/release/xen/${PORTVERSION}/
 PKGNAMESUFFIX=	-kernel
@@ -90,6 +90,8 @@ EXTRA_PATCHES=	${FILESDIR}/0001-xen-logdirty-prevent-p
 		${FILESDIR}/xsa249.patch:-p1 \
 		${FILESDIR}/xsa250.patch:-p1 \
 		${FILESDIR}/xsa251-4.8.patch:-p1 \
+		${FILESDIR}/0001-x86-entry-Remove-support-for-partial-cpu_user_regs-f.patch:-p1 \
+		${FILESDIR}/0001-x86-mm-Always-set-_PAGE_ACCESSED-on-L4e-updates.patch:-p1 \
 		${FILESDIR}/0001-x86-Meltdown-band-aid-against-malicious-64-bit-PV-gu.patch:-p1 \
 		${FILESDIR}/0002-x86-allow-Meltdown-band-aid-to-be-disabled.patch:-p1
 

Added: head/emulators/xen-kernel/files/0001-x86-entry-Remove-support-for-partial-cpu_user_regs-f.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/emulators/xen-kernel/files/0001-x86-entry-Remove-support-for-partial-cpu_user_regs-f.patch	Wed Jan 24 08:51:37 2018	(r459822)
@@ -0,0 +1,399 @@
+From 0e6c6fc449000d97f9fa87ed1fbe23f0cf21406b Mon Sep 17 00:00:00 2001
+From: Andrew Cooper <andrew.cooper3 at citrix.com>
+Date: Wed, 17 Jan 2018 17:22:34 +0100
+Subject: [PATCH] x86/entry: Remove support for partial cpu_user_regs frames
+
+Save all GPRs on entry to Xen.
+
+The entry_int82() path is via a DPL1 gate, only usable by 32bit PV guests, so
+can get away with only saving the 32bit registers.  All other entrypoints can
+be reached from 32 or 64bit contexts.
+
+This is part of XSA-254.
+
+Signed-off-by: Andrew Cooper <andrew.cooper3 at citrix.com>
+Reviewed-by: Wei Liu <wei.liu2 at citrix.com>
+Acked-by: Jan Beulich <jbeulich at suse.com>
+master commit: f9eb74789af77e985ae653193f3622263499f674
+master date: 2018-01-05 19:57:07 +0000
+---
+ tools/tests/x86_emulator/x86_emulate.c |   1 -
+ xen/arch/x86/domain.c                  |   1 -
+ xen/arch/x86/traps.c                   |   2 -
+ xen/arch/x86/x86_64/compat/entry.S     |   7 ++-
+ xen/arch/x86/x86_64/entry.S            |  12 ++--
+ xen/arch/x86/x86_64/traps.c            |  13 ++--
+ xen/arch/x86/x86_emulate.c             |   1 -
+ xen/arch/x86/x86_emulate/x86_emulate.c |   8 +--
+ xen/common/wait.c                      |   1 -
+ xen/include/asm-x86/asm_defns.h        | 107 +++------------------------------
+ 10 files changed, 26 insertions(+), 127 deletions(-)
+
+diff --git a/tools/tests/x86_emulator/x86_emulate.c b/tools/tests/x86_emulator/x86_emulate.c
+index 10e3f61baa..c12527a50b 100644
+--- a/tools/tests/x86_emulator/x86_emulate.c
++++ b/tools/tests/x86_emulator/x86_emulate.c
+@@ -24,7 +24,6 @@ typedef bool bool_t;
+ #endif
+ 
+ #define cpu_has_amd_erratum(nr) 0
+-#define mark_regs_dirty(r) ((void)(r))
+ 
+ #define __packed __attribute__((packed))
+ 
+diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
+index ceeadabbfd..6539b75fa7 100644
+--- a/xen/arch/x86/domain.c
++++ b/xen/arch/x86/domain.c
+@@ -148,7 +148,6 @@ static void noreturn continue_idle_domain(struct vcpu *v)
+ static void noreturn continue_nonidle_domain(struct vcpu *v)
+ {
+     check_wakeup_from_wait();
+-    mark_regs_dirty(guest_cpu_user_regs());
+     reset_stack_and_jump(ret_from_intr);
+ }
+ 
+diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
+index 05b4b0811d..0928c9b235 100644
+--- a/xen/arch/x86/traps.c
++++ b/xen/arch/x86/traps.c
+@@ -2456,7 +2456,6 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
+             goto fail;
+         if ( admin_io_okay(port, op_bytes, currd) )
+         {
+-            mark_regs_dirty(regs);
+             io_emul(regs);            
+         }
+         else
+@@ -2486,7 +2485,6 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
+             goto fail;
+         if ( admin_io_okay(port, op_bytes, currd) )
+         {
+-            mark_regs_dirty(regs);
+             io_emul(regs);            
+             if ( (op_bytes == 1) && pv_post_outb_hook )
+                 pv_post_outb_hook(port, regs->eax);
+diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S
+index 794bb44266..7ee01597a3 100644
+--- a/xen/arch/x86/x86_64/compat/entry.S
++++ b/xen/arch/x86/x86_64/compat/entry.S
+@@ -15,7 +15,8 @@
+ ENTRY(compat_hypercall)
+         ASM_CLAC
+         pushq $0
+-        SAVE_VOLATILE type=TRAP_syscall compat=1
++        movl  $TRAP_syscall, 4(%rsp)
++        SAVE_ALL compat=1 /* DPL1 gate, restricted to 32bit PV guests only. */
+         CR4_PV32_RESTORE
+ 
+         cmpb  $0,untrusted_msi(%rip)
+@@ -127,7 +128,6 @@ compat_test_guest_events:
+ /* %rbx: struct vcpu */
+ compat_process_softirqs:
+         sti
+-        andl  $~TRAP_regs_partial,UREGS_entry_vector(%rsp)
+         call  do_softirq
+         jmp   compat_test_all_events
+ 
+@@ -268,7 +268,8 @@ ENTRY(cstar_enter)
+         pushq $FLAT_USER_CS32
+         pushq %rcx
+         pushq $0
+-        SAVE_VOLATILE TRAP_syscall
++        movl  $TRAP_syscall, 4(%rsp)
++        SAVE_ALL
+         GET_CURRENT(bx)
+         movq  VCPU_domain(%rbx),%rcx
+         cmpb  $0,DOMAIN_is_32bit_pv(%rcx)
+diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
+index 708d9b9402..cebb1e4f4f 100644
+--- a/xen/arch/x86/x86_64/entry.S
++++ b/xen/arch/x86/x86_64/entry.S
+@@ -97,7 +97,8 @@ ENTRY(lstar_enter)
+         pushq $FLAT_KERNEL_CS64
+         pushq %rcx
+         pushq $0
+-        SAVE_VOLATILE TRAP_syscall
++        movl  $TRAP_syscall, 4(%rsp)
++        SAVE_ALL
+         GET_CURRENT(bx)
+         testb $TF_kernel_mode,VCPU_thread_flags(%rbx)
+         jz    switch_to_kernel
+@@ -192,7 +193,6 @@ test_guest_events:
+ /* %rbx: struct vcpu */
+ process_softirqs:
+         sti       
+-        SAVE_PRESERVED
+         call do_softirq
+         jmp  test_all_events
+ 
+@@ -246,7 +246,8 @@ GLOBAL(sysenter_eflags_saved)
+         pushq $3 /* ring 3 null cs */
+         pushq $0 /* null rip */
+         pushq $0
+-        SAVE_VOLATILE TRAP_syscall
++        movl  $TRAP_syscall, 4(%rsp)
++        SAVE_ALL
+         GET_CURRENT(bx)
+         cmpb  $0,VCPU_sysenter_disables_events(%rbx)
+         movq  VCPU_sysenter_addr(%rbx),%rax
+@@ -263,7 +264,6 @@ UNLIKELY_END(sysenter_nt_set)
+         leal  (,%rcx,TBF_INTERRUPT),%ecx
+ UNLIKELY_START(z, sysenter_gpf)
+         movq  VCPU_trap_ctxt(%rbx),%rsi
+-        SAVE_PRESERVED
+         movl  $TRAP_gp_fault,UREGS_entry_vector(%rsp)
+         movl  %eax,TRAPBOUNCE_error_code(%rdx)
+         movq  TRAP_gp_fault * TRAPINFO_sizeof + TRAPINFO_eip(%rsi),%rax
+@@ -281,7 +281,8 @@ UNLIKELY_END(sysenter_gpf)
+ ENTRY(int80_direct_trap)
+         ASM_CLAC
+         pushq $0
+-        SAVE_VOLATILE 0x80
++        movl  $0x80, 4(%rsp)
++        SAVE_ALL
+ 
+         cmpb  $0,untrusted_msi(%rip)
+ UNLIKELY_START(ne, msi_check)
+@@ -309,7 +310,6 @@ int80_slow_path:
+          * IDT entry with DPL==0.
+          */
+         movl  $((0x80 << 3) | X86_XEC_IDT),UREGS_error_code(%rsp)
+-        SAVE_PRESERVED
+         movl  $TRAP_gp_fault,UREGS_entry_vector(%rsp)
+         /* A GPF wouldn't have incremented the instruction pointer. */
+         subq  $2,UREGS_rip(%rsp)
+diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c
+index 22816100fd..bf8dfcbdee 100644
+--- a/xen/arch/x86/x86_64/traps.c
++++ b/xen/arch/x86/x86_64/traps.c
+@@ -81,15 +81,10 @@ static void _show_registers(
+            regs->rbp, regs->rsp, regs->r8);
+     printk("r9:  %016lx   r10: %016lx   r11: %016lx\n",
+            regs->r9,  regs->r10, regs->r11);
+-    if ( !(regs->entry_vector & TRAP_regs_partial) )
+-    {
+-        printk("r12: %016lx   r13: %016lx   r14: %016lx\n",
+-               regs->r12, regs->r13, regs->r14);
+-        printk("r15: %016lx   cr0: %016lx   cr4: %016lx\n",
+-               regs->r15, crs[0], crs[4]);
+-    }
+-    else
+-        printk("cr0: %016lx   cr4: %016lx\n", crs[0], crs[4]);
++    printk("r12: %016lx   r13: %016lx   r14: %016lx\n",
++           regs->r12, regs->r13, regs->r14);
++    printk("r15: %016lx   cr0: %016lx   cr4: %016lx\n",
++           regs->r15, crs[0], crs[4]);
+     printk("cr3: %016lx   cr2: %016lx\n", crs[3], crs[2]);
+     printk("fsb: %016lx   gsb: %016lx   gss: %016lx\n",
+            crs[5], crs[6], crs[7]);
+diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c
+index 28132b5dbc..43730026c2 100644
+--- a/xen/arch/x86/x86_emulate.c
++++ b/xen/arch/x86/x86_emulate.c
+@@ -11,7 +11,6 @@
+ 
+ #include <xen/domain_page.h>
+ #include <asm/x86_emulate.h>
+-#include <asm/asm_defns.h> /* mark_regs_dirty() */
+ #include <asm/processor.h> /* current_cpu_info */
+ #include <asm/amd.h> /* cpu_has_amd_erratum() */
+ 
+diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c
+index 4ee3df9247..fcfe9f7de7 100644
+--- a/xen/arch/x86/x86_emulate/x86_emulate.c
++++ b/xen/arch/x86/x86_emulate/x86_emulate.c
+@@ -1424,10 +1424,10 @@ decode_register(
+     case  9: p = &regs->r9;  break;
+     case 10: p = &regs->r10; break;
+     case 11: p = &regs->r11; break;
+-    case 12: mark_regs_dirty(regs); p = &regs->r12; break;
+-    case 13: mark_regs_dirty(regs); p = &regs->r13; break;
+-    case 14: mark_regs_dirty(regs); p = &regs->r14; break;
+-    case 15: mark_regs_dirty(regs); p = &regs->r15; break;
++    case 12: p = &regs->r12; break;
++    case 13: p = &regs->r13; break;
++    case 14: p = &regs->r14; break;
++    case 15: p = &regs->r15; break;
+ #endif
+     default: BUG(); p = NULL; break;
+     }
+diff --git a/xen/common/wait.c b/xen/common/wait.c
+index 4ac98c07fe..398f653174 100644
+--- a/xen/common/wait.c
++++ b/xen/common/wait.c
+@@ -128,7 +128,6 @@ static void __prepare_to_wait(struct waitqueue_vcpu *wqv)
+     unsigned long dummy;
+     u32 entry_vector = cpu_info->guest_cpu_user_regs.entry_vector;
+ 
+-    cpu_info->guest_cpu_user_regs.entry_vector &= ~TRAP_regs_partial;
+     ASSERT(wqv->esp == 0);
+ 
+     /* Save current VCPU affinity; force wakeup on *this* CPU only. */
+diff --git a/xen/include/asm-x86/asm_defns.h b/xen/include/asm-x86/asm_defns.h
+index 279d70298f..6e5c079ad8 100644
+--- a/xen/include/asm-x86/asm_defns.h
++++ b/xen/include/asm-x86/asm_defns.h
+@@ -17,15 +17,6 @@
+ void ret_from_intr(void);
+ #endif
+ 
+-#ifdef CONFIG_FRAME_POINTER
+-/* Indicate special exception stack frame by inverting the frame pointer. */
+-#define SETUP_EXCEPTION_FRAME_POINTER(offs)     \
+-        leaq  offs(%rsp),%rbp;                  \
+-        notq  %rbp
+-#else
+-#define SETUP_EXCEPTION_FRAME_POINTER(offs)
+-#endif
+-
+ #ifndef NDEBUG
+ #define ASSERT_INTERRUPT_STATUS(x, msg)         \
+         pushf;                                  \
+@@ -42,31 +33,6 @@ void ret_from_intr(void);
+ #define ASSERT_INTERRUPTS_DISABLED \
+     ASSERT_INTERRUPT_STATUS(z, "INTERRUPTS DISABLED")
+ 
+-/*
+- * This flag is set in an exception frame when registers R12-R15 did not get
+- * saved.
+- */
+-#define _TRAP_regs_partial 16
+-#define TRAP_regs_partial  (1 << _TRAP_regs_partial)
+-/*
+- * This flag gets set in an exception frame when registers R12-R15 possibly
+- * get modified from their originally saved values and hence need to be
+- * restored even if the normal call flow would restore register values.
+- *
+- * The flag being set implies _TRAP_regs_partial to be unset. Restoring
+- * R12-R15 thus is
+- * - required when this flag is set,
+- * - safe when _TRAP_regs_partial is unset.
+- */
+-#define _TRAP_regs_dirty   17
+-#define TRAP_regs_dirty    (1 << _TRAP_regs_dirty)
+-
+-#define mark_regs_dirty(r) ({ \
+-        struct cpu_user_regs *r__ = (r); \
+-        ASSERT(!((r__)->entry_vector & TRAP_regs_partial)); \
+-        r__->entry_vector |= TRAP_regs_dirty; \
+-})
+-
+ #ifdef __ASSEMBLY__
+ # define _ASM_EX(p) p-.
+ #else
+@@ -236,7 +202,7 @@ static always_inline void stac(void)
+ #endif
+ 
+ #ifdef __ASSEMBLY__
+-.macro SAVE_ALL op
++.macro SAVE_ALL op, compat=0
+ .ifeqs "\op", "CLAC"
+         ASM_CLAC
+ .else
+@@ -255,40 +221,6 @@ static always_inline void stac(void)
+         movq  %rdx,UREGS_rdx(%rsp)
+         movq  %rcx,UREGS_rcx(%rsp)
+         movq  %rax,UREGS_rax(%rsp)
+-        movq  %r8,UREGS_r8(%rsp)
+-        movq  %r9,UREGS_r9(%rsp)
+-        movq  %r10,UREGS_r10(%rsp)
+-        movq  %r11,UREGS_r11(%rsp)
+-        movq  %rbx,UREGS_rbx(%rsp)
+-        movq  %rbp,UREGS_rbp(%rsp)
+-        SETUP_EXCEPTION_FRAME_POINTER(UREGS_rbp)
+-        movq  %r12,UREGS_r12(%rsp)
+-        movq  %r13,UREGS_r13(%rsp)
+-        movq  %r14,UREGS_r14(%rsp)
+-        movq  %r15,UREGS_r15(%rsp)
+-.endm
+-
+-/*
+- * Save all registers not preserved by C code or used in entry/exit code. Mark
+- * the frame as partial.
+- *
+- * @type: exception type
+- * @compat: R8-R15 don't need saving, and the frame nevertheless is complete
+- */
+-.macro SAVE_VOLATILE type compat=0
+-.if \compat
+-        movl  $\type,UREGS_entry_vector-UREGS_error_code(%rsp)
+-.else
+-        movl  $\type|TRAP_regs_partial,\
+-              UREGS_entry_vector-UREGS_error_code(%rsp)
+-.endif
+-        addq  $-(UREGS_error_code-UREGS_r15),%rsp
+-        cld
+-        movq  %rdi,UREGS_rdi(%rsp)
+-        movq  %rsi,UREGS_rsi(%rsp)
+-        movq  %rdx,UREGS_rdx(%rsp)
+-        movq  %rcx,UREGS_rcx(%rsp)
+-        movq  %rax,UREGS_rax(%rsp)
+ .if !\compat
+         movq  %r8,UREGS_r8(%rsp)
+         movq  %r9,UREGS_r9(%rsp)
+@@ -297,20 +229,17 @@ static always_inline void stac(void)
+ .endif
+         movq  %rbx,UREGS_rbx(%rsp)
+         movq  %rbp,UREGS_rbp(%rsp)
+-        SETUP_EXCEPTION_FRAME_POINTER(UREGS_rbp)
+-.endm
+-
+-/*
+- * Complete a frame potentially only partially saved.
+- */
+-.macro SAVE_PRESERVED
+-        btrl  $_TRAP_regs_partial,UREGS_entry_vector(%rsp)
+-        jnc   987f
++#ifdef CONFIG_FRAME_POINTER
++/* Indicate special exception stack frame by inverting the frame pointer. */
++        leaq  UREGS_rbp(%rsp), %rbp
++        notq  %rbp
++#endif
++.if !\compat
+         movq  %r12,UREGS_r12(%rsp)
+         movq  %r13,UREGS_r13(%rsp)
+         movq  %r14,UREGS_r14(%rsp)
+         movq  %r15,UREGS_r15(%rsp)
+-987:
++.endif
+ .endm
+ 
+ #define LOAD_ONE_REG(reg, compat) \
+@@ -351,33 +280,13 @@ static always_inline void stac(void)
+  * @compat: R8-R15 don't need reloading
+  */
+ .macro RESTORE_ALL adj=0 compat=0
+-.if !\compat
+-        testl $TRAP_regs_dirty,UREGS_entry_vector(%rsp)
+-.endif
+         LOAD_C_CLOBBERED \compat
+ .if !\compat
+-        jz    987f
+         movq  UREGS_r15(%rsp),%r15
+         movq  UREGS_r14(%rsp),%r14
+         movq  UREGS_r13(%rsp),%r13
+         movq  UREGS_r12(%rsp),%r12
+-#ifndef NDEBUG
+-        .subsection 1
+-987:    testl $TRAP_regs_partial,UREGS_entry_vector(%rsp)
+-        jnz   987f
+-        cmpq  UREGS_r15(%rsp),%r15
+-        jne   789f
+-        cmpq  UREGS_r14(%rsp),%r14
+-        jne   789f
+-        cmpq  UREGS_r13(%rsp),%r13
+-        jne   789f
+-        cmpq  UREGS_r12(%rsp),%r12
+-        je    987f
+-789:    BUG   /* Corruption of partial register state. */
+-        .subsection 0
+-#endif
+ .endif
+-987:
+         LOAD_ONE_REG(bp, \compat)
+         LOAD_ONE_REG(bx, \compat)
+         subq  $-(UREGS_error_code-UREGS_r15+\adj), %rsp
+-- 
+2.15.1
+

Added: head/emulators/xen-kernel/files/0001-x86-mm-Always-set-_PAGE_ACCESSED-on-L4e-updates.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/emulators/xen-kernel/files/0001-x86-mm-Always-set-_PAGE_ACCESSED-on-L4e-updates.patch	Wed Jan 24 08:51:37 2018	(r459822)
@@ -0,0 +1,45 @@
+From 9b76908e6e074d7efbeafe6bad066ecc5f3c3c43 Mon Sep 17 00:00:00 2001
+From: Andrew Cooper <andrew.cooper3 at citrix.com>
+Date: Wed, 17 Jan 2018 17:23:37 +0100
+Subject: [PATCH] x86/mm: Always set _PAGE_ACCESSED on L4e updates
+
+Signed-off-by: Andrew Cooper <andrew.cooper3 at citrix.com>
+Reviewed-by: Jan Beulich <jbeulich at suse.com>
+master commit: bd61fe94bee0556bc2f64999a4a8315b93f90f21
+master date: 2018-01-15 13:53:16 +0000
+---
+ xen/arch/x86/mm.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
+index ada12c05c5..50f500c940 100644
+--- a/xen/arch/x86/mm.c
++++ b/xen/arch/x86/mm.c
+@@ -1296,11 +1296,23 @@ get_page_from_l4e(
+                                          _PAGE_USER|_PAGE_RW);      \
+     } while ( 0 )
+ 
++/*
++ * When shadowing an L4 behind the guests back (e.g. for per-pcpu
++ * purposes), we cannot efficiently sync access bit updates from hardware
++ * (on the shadow tables) back into the guest view.
++ *
++ * We therefore unconditionally set _PAGE_ACCESSED even in the guests
++ * view.  This will appear to the guest as a CPU which proactively pulls
++ * all valid L4e's into its TLB, which is compatible with the x86 ABI.
++ *
++ * At the time of writing, all PV guests set the access bit anyway, so
++ * this is no actual change in their behaviour.
++ */
+ #define adjust_guest_l4e(pl4e, d)                               \
+     do {                                                        \
+         if ( likely(l4e_get_flags((pl4e)) & _PAGE_PRESENT) &&   \
+              likely(!is_pv_32bit_domain(d)) )                   \
+-            l4e_add_flags((pl4e), _PAGE_USER);                  \
++            l4e_add_flags((pl4e), _PAGE_USER | _PAGE_ACCESSED); \
+     } while ( 0 )
+ 
+ #define unadjust_guest_l3e(pl3e, d)                                         \
+-- 
+2.15.1
+


More information about the svn-ports-all mailing list