* [PATCH 0/2] KVM/arm: add fp/simd lazy switch support
@ 2015-09-18 1:05 Mario Smarduch
2015-09-18 1:05 ` [PATCH 1/2] KVM/arm: add hooks for armv7 " Mario Smarduch
2015-09-18 1:05 ` [PATCH 2/2] KVM/arm: enable armv7 fp/simd lazy switch Mario Smarduch
0 siblings, 2 replies; 5+ messages in thread
From: Mario Smarduch @ 2015-09-18 1:05 UTC (permalink / raw)
To: linux-arm-kernel
These patches enable armv7 fp/simd lazy switch. On guest entry fp/simd
access trap is set, and on guest first access fp/simd registers are switched -
host saved, guest restored. CPU continues with guest fp/simd content until
vcpu_put where guest is saved and host is restored.
Running floating point workload illustrates reduction of fp/simd context
switches the amount depends on the load. For a light load with with FP
application running only 2% of all exits result in calls to lazy switch.
arm64 version is in test and appears to work fine, remaining work is
boot arm32 guest on arm64 and verify operation. Initial intent was to post
all patches at once, but arm64 version will be posted soon.
Mario Smarduch (2):
add hooks for armv7 vfp/simd lazy switch support
enable armv7 vfp/simd lazy switch
arch/arm/include/asm/kvm_asm.h | 1 +
arch/arm/include/asm/kvm_host.h | 3 +++
arch/arm/kernel/asm-offsets.c | 1 +
arch/arm/kvm/arm.c | 17 +++++++++++++++++
arch/arm/kvm/interrupts.S | 40 +++++++++++++++++++++++++++++-----------
5 files changed, 51 insertions(+), 11 deletions(-)
--
1.9.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] KVM/arm: add hooks for armv7 fp/simd lazy switch support
2015-09-18 1:05 [PATCH 0/2] KVM/arm: add fp/simd lazy switch support Mario Smarduch
@ 2015-09-18 1:05 ` Mario Smarduch
2015-09-18 1:05 ` [PATCH 2/2] KVM/arm: enable armv7 fp/simd lazy switch Mario Smarduch
1 sibling, 0 replies; 5+ messages in thread
From: Mario Smarduch @ 2015-09-18 1:05 UTC (permalink / raw)
To: linux-arm-kernel
Basic hooks are added to support fp/simd lazy switch. A vcpu flag to track
fp/simd state, offset into the vcpu structure and switch prototype function.
Signed-off-by: Mario Smarduch <m.smarduch@samsung.com>
---
arch/arm/include/asm/kvm_asm.h | 1 +
arch/arm/include/asm/kvm_host.h | 3 +++
arch/arm/kernel/asm-offsets.c | 1 +
3 files changed, 5 insertions(+)
diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
index 194c91b..4b45d79 100644
--- a/arch/arm/include/asm/kvm_asm.h
+++ b/arch/arm/include/asm/kvm_asm.h
@@ -97,6 +97,7 @@ extern char __kvm_hyp_code_end[];
extern void __kvm_flush_vm_context(void);
extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
+extern void __kvm_restore_host_vfp_state(struct kvm_vcpu *vcpu);
extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
#endif
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index dcba0fa..4858f6c 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -111,6 +111,9 @@ struct kvm_vcpu_arch {
/* Interrupt related fields */
u32 irq_lines; /* IRQ and FIQ levels */
+ /* Track fp/simd lazy switch */
+ u32 vfp_lazy;
+
/* Exception Information */
struct kvm_vcpu_fault_info fault;
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 871b826..4a80802f 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -191,6 +191,7 @@ int main(void)
DEFINE(VCPU_HPFAR, offsetof(struct kvm_vcpu, arch.fault.hpfar));
DEFINE(VCPU_HYP_PC, offsetof(struct kvm_vcpu, arch.fault.hyp_pc));
DEFINE(VCPU_VGIC_CPU, offsetof(struct kvm_vcpu, arch.vgic_cpu));
+ DEFINE(VCPU_VFP_LAZY, offsetof(struct kvm_vcpu, arch.vfp_lazy));
DEFINE(VGIC_V2_CPU_HCR, offsetof(struct vgic_cpu, vgic_v2.vgic_hcr));
DEFINE(VGIC_V2_CPU_VMCR, offsetof(struct vgic_cpu, vgic_v2.vgic_vmcr));
DEFINE(VGIC_V2_CPU_MISR, offsetof(struct vgic_cpu, vgic_v2.vgic_misr));
--
1.9.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] KVM/arm: enable armv7 fp/simd lazy switch
2015-09-18 1:05 [PATCH 0/2] KVM/arm: add fp/simd lazy switch support Mario Smarduch
2015-09-18 1:05 ` [PATCH 1/2] KVM/arm: add hooks for armv7 " Mario Smarduch
@ 2015-09-18 1:05 ` Mario Smarduch
2015-09-22 14:01 ` Antonios Motakis
1 sibling, 1 reply; 5+ messages in thread
From: Mario Smarduch @ 2015-09-18 1:05 UTC (permalink / raw)
To: linux-arm-kernel
Adds code to enable fp/simd lazy switch. On each entry check if fp/simd
registers have been switched to guest, if no set the trap flag. On trap
switch fp/simd registers and set vfp_lazy to true and disable trapping.
When the vcpu is about to be put, then context switch fp/simd registers
save guest and restore host and reset the vfp_lazy state to enable trapping
again.
Signed-off-by: Mario Smarduch <m.smarduch@samsung.com>
---
arch/arm/kvm/arm.c | 17 +++++++++++++++++
arch/arm/kvm/interrupts.S | 40 +++++++++++++++++++++++++++++-----------
2 files changed, 46 insertions(+), 11 deletions(-)
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index ce404a5..0acbb69 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -105,6 +105,20 @@ void kvm_arch_check_processor_compat(void *rtn)
*(int *)rtn = 0;
}
+/**
+ * kvm_switch_fp_regs() - switch guest/host VFP/SIMD registers
+ * @vcpu: pointer to vcpu structure.
+ *
+ */
+static void kvm_switch_fp_regs(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_ARM
+ if (vcpu->arch.vfp_lazy == 1) {
+ kvm_call_hyp(__kvm_restore_host_vfp_state, vcpu);
+ vcpu->arch.vfp_lazy = 0;
+ }
+#endif
+}
/**
* kvm_arch_init_vm - initializes a VM data structure
@@ -295,6 +309,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
{
+ /* Check if Guest accessed VFP registers */
+ kvm_switch_fp_regs(vcpu);
+
/*
* The arch-generic KVM code expects the cpu field of a vcpu to be -1
* if the vcpu is no longer assigned to a cpu. This is used for the
diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S
index 900ef6d..a47acc1 100644
--- a/arch/arm/kvm/interrupts.S
+++ b/arch/arm/kvm/interrupts.S
@@ -96,6 +96,24 @@ ENTRY(__kvm_flush_vm_context)
bx lr
ENDPROC(__kvm_flush_vm_context)
+/**
+ * void __kvm_restore_host_vfp_state(struct vcpu *vcpu) - Executes a lazy
+ * fp/simd switch, saves the guest, restores host.
+ *
+ */
+ENTRY(__kvm_restore_host_vfp_state)
+ push {r3-r7}
+
+ add r7, r0, #VCPU_VFP_GUEST
+ store_vfp_state r7
+
+ add r7, r0, #VCPU_VFP_HOST
+ ldr r7, [r7]
+ restore_vfp_state r7
+
+ pop {r3-r7}
+ bx lr
+ENDPROC(__kvm_restore_host_vfp_state)
/********************************************************************
* Hypervisor world-switch code
@@ -131,7 +149,14 @@ ENTRY(__kvm_vcpu_run)
@ Trap coprocessor CRx accesses
set_hstr vmentry
+
+ ldr r1, [vcpu, #VCPU_VFP_LAZY]
+ cmp r1, #1
+ beq skip_guest_vfp_trap
+
set_hcptr vmentry, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11))
+skip_guest_vfp_trap:
+
set_hdcr vmentry
@ Write configured ID register into MIDR alias
@@ -170,22 +195,12 @@ __kvm_vcpu_return:
@ Don't trap coprocessor accesses for host kernel
set_hstr vmexit
set_hdcr vmexit
- set_hcptr vmexit, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11)), after_vfp_restore
+ set_hcptr vmexit, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11))
#ifdef CONFIG_VFPv3
- @ Switch VFP/NEON hardware state to the host's
- add r7, vcpu, #VCPU_VFP_GUEST
- store_vfp_state r7
- add r7, vcpu, #VCPU_VFP_HOST
- ldr r7, [r7]
- restore_vfp_state r7
-
-after_vfp_restore:
@ Restore FPEXC_EN which we clobbered on entry
pop {r2}
VFPFMXR FPEXC, r2
-#else
-after_vfp_restore:
#endif
@ Reset Hyp-role
@@ -485,6 +500,9 @@ switch_to_guest_vfp:
@ NEON/VFP used. Turn on VFP access.
set_hcptr vmtrap, (HCPTR_TCP(10) | HCPTR_TCP(11))
+ mov r1, #1
+ str r1, [vcpu, #VCPU_VFP_LAZY]
+
@ Switch VFP/NEON hardware state to the guest's
add r7, r0, #VCPU_VFP_HOST
ldr r7, [r7]
--
1.9.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] KVM/arm: enable armv7 fp/simd lazy switch
2015-09-18 1:05 ` [PATCH 2/2] KVM/arm: enable armv7 fp/simd lazy switch Mario Smarduch
@ 2015-09-22 14:01 ` Antonios Motakis
2015-09-23 0:39 ` Mario Smarduch
0 siblings, 1 reply; 5+ messages in thread
From: Antonios Motakis @ 2015-09-22 14:01 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
On 18-Sep-15 03:05, Mario Smarduch wrote:
> Adds code to enable fp/simd lazy switch. On each entry check if fp/simd
> registers have been switched to guest, if no set the trap flag. On trap
> switch fp/simd registers and set vfp_lazy to true and disable trapping.
> When the vcpu is about to be put, then context switch fp/simd registers
> save guest and restore host and reset the vfp_lazy state to enable trapping
> again.
>
This description confused me a bit, since KVM on ARMv7 already exhibits
lazy switching behavior for VFP. Should the description highlight the
intended improvement in behavior?
If I understand correctly, instead of restoring the host state on every
exit, you postpone it until the task actually gets rescheduled, right?
> Signed-off-by: Mario Smarduch <m.smarduch@samsung.com>
> ---
> arch/arm/kvm/arm.c | 17 +++++++++++++++++
> arch/arm/kvm/interrupts.S | 40 +++++++++++++++++++++++++++++-----------
> 2 files changed, 46 insertions(+), 11 deletions(-)
>
> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> index ce404a5..0acbb69 100644
> --- a/arch/arm/kvm/arm.c
> +++ b/arch/arm/kvm/arm.c
> @@ -105,6 +105,20 @@ void kvm_arch_check_processor_compat(void *rtn)
> *(int *)rtn = 0;
> }
>
> +/**
> + * kvm_switch_fp_regs() - switch guest/host VFP/SIMD registers
> + * @vcpu: pointer to vcpu structure.
> + *
> + */
> +static void kvm_switch_fp_regs(struct kvm_vcpu *vcpu)
> +{
> +#ifdef CONFIG_ARM
> + if (vcpu->arch.vfp_lazy == 1) {
> + kvm_call_hyp(__kvm_restore_host_vfp_state, vcpu);
> + vcpu->arch.vfp_lazy = 0;
> + }
> +#endif
> +}
>
> /**
> * kvm_arch_init_vm - initializes a VM data structure
> @@ -295,6 +309,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
>
> void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
> {
> + /* Check if Guest accessed VFP registers */
> + kvm_switch_fp_regs(vcpu);
> +
> /*
> * The arch-generic KVM code expects the cpu field of a vcpu to be -1
> * if the vcpu is no longer assigned to a cpu. This is used for the
> diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S
> index 900ef6d..a47acc1 100644
> --- a/arch/arm/kvm/interrupts.S
> +++ b/arch/arm/kvm/interrupts.S
> @@ -96,6 +96,24 @@ ENTRY(__kvm_flush_vm_context)
> bx lr
> ENDPROC(__kvm_flush_vm_context)
>
> +/**
> + * void __kvm_restore_host_vfp_state(struct vcpu *vcpu) - Executes a lazy
> + * fp/simd switch, saves the guest, restores host.
> + *
> + */
> +ENTRY(__kvm_restore_host_vfp_state)
> + push {r3-r7}
> +
> + add r7, r0, #VCPU_VFP_GUEST
> + store_vfp_state r7
> +
> + add r7, r0, #VCPU_VFP_HOST
> + ldr r7, [r7]
> + restore_vfp_state r7
> +
> + pop {r3-r7}
> + bx lr
> +ENDPROC(__kvm_restore_host_vfp_state)
>
> /********************************************************************
> * Hypervisor world-switch code
> @@ -131,7 +149,14 @@ ENTRY(__kvm_vcpu_run)
>
> @ Trap coprocessor CRx accesses
> set_hstr vmentry
> +
> + ldr r1, [vcpu, #VCPU_VFP_LAZY]
> + cmp r1, #1
> + beq skip_guest_vfp_trap
> +
> set_hcptr vmentry, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11))
> +skip_guest_vfp_trap:
I believe that HCPTR_TTA is not part of the floating point extensions.
> +
> set_hdcr vmentry
>
> @ Write configured ID register into MIDR alias
> @@ -170,22 +195,12 @@ __kvm_vcpu_return:
> @ Don't trap coprocessor accesses for host kernel
> set_hstr vmexit
> set_hdcr vmexit
> - set_hcptr vmexit, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11)), after_vfp_restore
> + set_hcptr vmexit, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11))
If you don't use the functionality of the macro to branch on change,
then maybe the functionality should also be removed from the macro.
>
> #ifdef CONFIG_VFPv3
> - @ Switch VFP/NEON hardware state to the host's
> - add r7, vcpu, #VCPU_VFP_GUEST
> - store_vfp_state r7
> - add r7, vcpu, #VCPU_VFP_HOST
> - ldr r7, [r7]
> - restore_vfp_state r7
> -
> -after_vfp_restore:
> @ Restore FPEXC_EN which we clobbered on entry
> pop {r2}
> VFPFMXR FPEXC, r2
> -#else
> -after_vfp_restore:
> #endif
>
> @ Reset Hyp-role
> @@ -485,6 +500,9 @@ switch_to_guest_vfp:
> @ NEON/VFP used. Turn on VFP access.
> set_hcptr vmtrap, (HCPTR_TCP(10) | HCPTR_TCP(11))
>
> + mov r1, #1
> + str r1, [vcpu, #VCPU_VFP_LAZY]
> +
> @ Switch VFP/NEON hardware state to the guest's
> add r7, r0, #VCPU_VFP_HOST
> ldr r7, [r7]
>
--
Antonios Motakis
Virtualization Engineer
Huawei Technologies Duesseldorf GmbH
European Research Center
Riesstrasse 25, 80992 M?nchen
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/2] KVM/arm: enable armv7 fp/simd lazy switch
2015-09-22 14:01 ` Antonios Motakis
@ 2015-09-23 0:39 ` Mario Smarduch
0 siblings, 0 replies; 5+ messages in thread
From: Mario Smarduch @ 2015-09-23 0:39 UTC (permalink / raw)
To: linux-arm-kernel
Hi Antonios,
On 9/22/2015 7:01 AM, Antonios Motakis wrote:
> Hello,
>
> On 18-Sep-15 03:05, Mario Smarduch wrote:
>> Adds code to enable fp/simd lazy switch. On each entry check if fp/simd
>> registers have been switched to guest, if no set the trap flag. On trap
>> switch fp/simd registers and set vfp_lazy to true and disable trapping.
>> When the vcpu is about to be put, then context switch fp/simd registers
>> save guest and restore host and reset the vfp_lazy state to enable trapping
>> again.
>>
>
> This description confused me a bit, since KVM on ARMv7 already exhibits
> lazy switching behavior for VFP. Should the description highlight the
> intended improvement in behavior?
>
> If I understand correctly, instead of restoring the host state on every
> exit, you postpone it until the task actually gets rescheduled, right?
Yes that's right, I'll reword to highlight the changes.
>
>> Signed-off-by: Mario Smarduch <m.smarduch@samsung.com>
>> ---
>> arch/arm/kvm/arm.c | 17 +++++++++++++++++
>> arch/arm/kvm/interrupts.S | 40 +++++++++++++++++++++++++++++-----------
>> 2 files changed, 46 insertions(+), 11 deletions(-)
>>
>> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
>> index ce404a5..0acbb69 100644
>> --- a/arch/arm/kvm/arm.c
>> +++ b/arch/arm/kvm/arm.c
>> @@ -105,6 +105,20 @@ void kvm_arch_check_processor_compat(void *rtn)
>> *(int *)rtn = 0;
>> }
>>
>> +/**
>> + * kvm_switch_fp_regs() - switch guest/host VFP/SIMD registers
>> + * @vcpu: pointer to vcpu structure.
>> + *
>> + */
>> +static void kvm_switch_fp_regs(struct kvm_vcpu *vcpu)
>> +{
>> +#ifdef CONFIG_ARM
>> + if (vcpu->arch.vfp_lazy == 1) {
>> + kvm_call_hyp(__kvm_restore_host_vfp_state, vcpu);
>> + vcpu->arch.vfp_lazy = 0;
>> + }
>> +#endif
>> +}
>>
>> /**
>> * kvm_arch_init_vm - initializes a VM data structure
>> @@ -295,6 +309,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
>>
>> void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
>> {
>> + /* Check if Guest accessed VFP registers */
>> + kvm_switch_fp_regs(vcpu);
>> +
>> /*
>> * The arch-generic KVM code expects the cpu field of a vcpu to be -1
>> * if the vcpu is no longer assigned to a cpu. This is used for the
>> diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S
>> index 900ef6d..a47acc1 100644
>> --- a/arch/arm/kvm/interrupts.S
>> +++ b/arch/arm/kvm/interrupts.S
>> @@ -96,6 +96,24 @@ ENTRY(__kvm_flush_vm_context)
>> bx lr
>> ENDPROC(__kvm_flush_vm_context)
>>
>> +/**
>> + * void __kvm_restore_host_vfp_state(struct vcpu *vcpu) - Executes a lazy
>> + * fp/simd switch, saves the guest, restores host.
>> + *
>> + */
>> +ENTRY(__kvm_restore_host_vfp_state)
>> + push {r3-r7}
>> +
>> + add r7, r0, #VCPU_VFP_GUEST
>> + store_vfp_state r7
>> +
>> + add r7, r0, #VCPU_VFP_HOST
>> + ldr r7, [r7]
>> + restore_vfp_state r7
>> +
>> + pop {r3-r7}
>> + bx lr
>> +ENDPROC(__kvm_restore_host_vfp_state)
>>
>> /********************************************************************
>> * Hypervisor world-switch code
>> @@ -131,7 +149,14 @@ ENTRY(__kvm_vcpu_run)
>>
>> @ Trap coprocessor CRx accesses
>> set_hstr vmentry
>> +
>> + ldr r1, [vcpu, #VCPU_VFP_LAZY]
>> + cmp r1, #1
>> + beq skip_guest_vfp_trap
>> +
>> set_hcptr vmentry, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11))
>> +skip_guest_vfp_trap:
>
> I believe that HCPTR_TTA is not part of the floating point extensions.
Yes you're right trap on tracing is not enabled.
>
>> +
>> set_hdcr vmentry
>>
>> @ Write configured ID register into MIDR alias
>> @@ -170,22 +195,12 @@ __kvm_vcpu_return:
>> @ Don't trap coprocessor accesses for host kernel
>> set_hstr vmexit
>> set_hdcr vmexit
>> - set_hcptr vmexit, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11)), after_vfp_restore
>> + set_hcptr vmexit, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11))
>
> If you don't use the functionality of the macro to branch on change,
> then maybe the functionality should also be removed from the macro.
Yes, the macros needs to change.
>
>>
>> #ifdef CONFIG_VFPv3
>> - @ Switch VFP/NEON hardware state to the host's
>> - add r7, vcpu, #VCPU_VFP_GUEST
>> - store_vfp_state r7
>> - add r7, vcpu, #VCPU_VFP_HOST
>> - ldr r7, [r7]
>> - restore_vfp_state r7
>> -
>> -after_vfp_restore:
>> @ Restore FPEXC_EN which we clobbered on entry
>> pop {r2}
>> VFPFMXR FPEXC, r2
>> -#else
>> -after_vfp_restore:
>> #endif
>>
>> @ Reset Hyp-role
>> @@ -485,6 +500,9 @@ switch_to_guest_vfp:
>> @ NEON/VFP used. Turn on VFP access.
>> set_hcptr vmtrap, (HCPTR_TCP(10) | HCPTR_TCP(11))
>>
>> + mov r1, #1
>> + str r1, [vcpu, #VCPU_VFP_LAZY]
>> +
>> @ Switch VFP/NEON hardware state to the guest's
>> add r7, r0, #VCPU_VFP_HOST
>> ldr r7, [r7]
>>
>
Thanks for reviewing.
- Mario
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2015-09-23 0:39 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-09-18 1:05 [PATCH 0/2] KVM/arm: add fp/simd lazy switch support Mario Smarduch
2015-09-18 1:05 ` [PATCH 1/2] KVM/arm: add hooks for armv7 " Mario Smarduch
2015-09-18 1:05 ` [PATCH 2/2] KVM/arm: enable armv7 fp/simd lazy switch Mario Smarduch
2015-09-22 14:01 ` Antonios Motakis
2015-09-23 0:39 ` Mario Smarduch
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).