On Wed, Mar 16, 2016 at 11:25:11PM -0700, Mike Larkin wrote:
> On Thu, Mar 17, 2016 at 09:44:22AM +0900, Masao Uebayashi wrote:
> > Implement delay() using TSC
> > 
> > - Calculate delay using 64-bit RDTSC instruction
> > - Enable tsc_delay() as delay(9) backend
> > - Use tsc_delay() only when TSC is invariant
> > - Configure tsc_delay() after primary CPU is identified
> > - Assume all CPUs are identical
> 
> Why is this needed, or wanted? There is no explanation given above
> aside from "let's make things different". Are you claiming that
> delay(9) is somehow inaccurate or incorrect without this?

I think LAPIC delay() is just fine.  Accuracy is not a problem for me.

In the long run, I want to use LAPIC for per-CPU one-shot timer.  This
will come later ... but it'd be nice for me to know if using TSC for
delay() is not a problem.

> -ml
> 
> > 
> > diff --git a/sys/arch/amd64/amd64/cpu.c b/sys/arch/amd64/amd64/cpu.c
> > index df6c623..0863306 100644
> > --- a/sys/arch/amd64/amd64/cpu.c
> > +++ b/sys/arch/amd64/amd64/cpu.c
> > @@ -330,6 +330,7 @@ cpu_attach(struct device *parent, struct device *self, 
> > void *aux)
> >     vaddr_t kstack;
> >     struct pcb *pcb;
> >  #endif
> > +   void tsc_delay_init(struct cpu_info *);
> >  
> >     /*
> >      * If we're an Application Processor, allocate a cpu_info
> > @@ -409,6 +410,7 @@ cpu_attach(struct device *parent, struct device *self, 
> > void *aux)
> >  #endif /* MTRR */
> >             cpu_init(ci);
> >             cpu_init_mwait(sc);
> > +           tsc_delay_init(ci);
> >             break;
> >  
> >     case CPU_ROLE_BP:
> > @@ -432,6 +434,7 @@ cpu_attach(struct device *parent, struct device *self, 
> > void *aux)
> >             ioapic_bsp_id = caa->cpu_number;
> >  #endif
> >             cpu_init_mwait(sc);
> > +           tsc_delay_init(ci);
> >             break;
> >  
> >     case CPU_ROLE_AP:
> > diff --git a/sys/arch/amd64/amd64/tsc.c b/sys/arch/amd64/amd64/tsc.c
> > new file mode 100644
> > index 0000000..15242ca
> > --- /dev/null
> > +++ b/sys/arch/amd64/amd64/tsc.c
> > @@ -0,0 +1,68 @@
> > +/*
> > + * Copyright (c) 2016 Masao Uebayashi <[email protected]>
> > + *
> > + * Permission to use, copy, modify, and distribute this software for any
> > + * purpose with or without fee is hereby granted, provided that the above
> > + * copyright notice and this permission notice appear in all copies.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> > + */
> > +
> > +#include <sys/param.h>
> > +#include <sys/systm.h>
> > +#include <sys/stdint.h>
> > +
> > +#include <machine/cpu.h>
> > +#include <machine/cpufunc.h>
> > +
> > +void tsc_delay_init(struct cpu_info *);
> > +void tsc_delay(int);
> > +uint64_t tsc2usec(uint64_t n);
> > +
> > +int64_t tsc_delay_mult;
> > +
> > +void
> > +tsc_delay_init(struct cpu_info *ci)
> > +{
> > +#ifdef DIAGNOSTIC
> > +   KASSERT(ci->ci_tsc_freq != 0);
> > +#endif
> > +   if ((ci->ci_flags & CPUF_CONST_TSC) == 0)
> > +           return;
> > +
> > +   tsc_delay_mult = ci->ci_tsc_freq / 1000000;
> > +   delay_func = tsc_delay;
> > +}
> > +
> > +void
> > +tsc_delay(int usec)
> > +{
> > +   int64_t n;
> > +   uint64_t now, prev;
> > +
> > +   n = tsc_delay_mult * usec;
> > +   prev = rdtsc();
> > +   while (n > 0) {
> > +           CPU_BUSY_CYCLE();
> > +           now = rdtsc();
> > +           if (now < prev)
> > +                   n -= UINT64_MAX - (prev - now);
> > +           else
> > +                   n -= now - prev;
> > +           prev = now;
> > +   }
> > +}
> > +
> > +uint64_t
> > +tsc2usec(uint64_t n)
> > +{
> > +   struct cpu_info *ci = curcpu();
> > +
> > +   return n / ci->ci_tsc_freq * 1000000;
> > +}
> > diff --git a/sys/arch/amd64/conf/files.amd64 
> > b/sys/arch/amd64/conf/files.amd64
> > index 5d58b34..d101cf2 100644
> > --- a/sys/arch/amd64/conf/files.amd64
> > +++ b/sys/arch/amd64/conf/files.amd64
> > @@ -97,6 +97,7 @@ define    cpu {[apid = -1]}
> >  device     cpu
> >  attach     cpu at mainbus
> >  file       arch/amd64/amd64/cpu.c  cpu
> > +file       arch/amd64/amd64/tsc.c  cpu
> >  
> >  
> >  define     lapic
> > 

Reply via email to