All of lore.kernel.org
 help / color / mirror / Atom feed
From: Avi Kivity <avi@redhat.com>
To: Marcelo Tosatti <mtosatti@redhat.com>
Cc: kvm@vger.kernel.org, Zachary Amsden <zamsden@redhat.com>
Subject: Re: kvm: test: timer testcase
Date: Thu, 08 Oct 2009 14:37:29 +0200	[thread overview]
Message-ID: <4ACDDD09.6080302@redhat.com> (raw)
In-Reply-To: <20091007190201.GA6418@amt.cnet>

On 10/07/2009 09:02 PM, Marcelo Tosatti wrote:
>
> Test timer interrupts (HPET, LAPIC, PIT) in correlation with
> ACPI/TSC counters.
>
> New tests/variations are easy to add.
>
> Signed-off-by: Marcelo Tosatti<mtosatti@redhat.com>
>
> Index: qemu-kvm/kvm/user/config-x86-common.mak
> ===================================================================
> --- qemu-kvm.orig/kvm/user/config-x86-common.mak
> +++ qemu-kvm/kvm/user/config-x86-common.mak
> @@ -58,6 +58,9 @@ $(TEST_DIR)/tsc.flat: $(cstart.o) $(TEST
>   $(TEST_DIR)/apic.flat: $(cstart.o) $(TEST_DIR)/apic.o $(TEST_DIR)/vm.o \
>   		       $(TEST_DIR)/print.o
>
> +$(TEST_DIR)/time.flat: $(cstart.o) $(TEST_DIR)/time.o $(TEST_DIR)/vm.o \
> +		       $(TEST_DIR)/print.o
>    

Is print.o really needed?

> ===================================================================
> --- /dev/null
> +++ qemu-kvm/kvm/user/test/x86/io.h
> @@ -0,0 +1,35 @@
> +static inline void outb(unsigned char val, unsigned short port)
> +{
> +	asm volatile("outb %0, %w1": : "a"(val), "Nd" (port));
> +}
> +
> +static inline void outw(unsigned short val, unsigned short port)
> +{
> +	asm volatile("outw %0, %w1": : "a"(val), "Nd" (port));
> +}
> +
> +static inline void outl(unsigned long val, unsigned short port)
> +{
> +	asm volatile("outl %0, %w1": : "a"(val), "Nd" (port));
> +}
> +
> +static inline unsigned char inb(unsigned short port)
> +{
> +	unsigned char val;
> +	asm volatile("inb %w1, %0": "=a"(val) : "Nd" (port));
> +	return val;
> +}
> +
> +static inline short inw(unsigned short port)
> +{
> +	short val;
> +	asm volatile("inw %w1, %0": "=a"(val) : "Nd" (port));
> +	return val;
> +}
> +
> +static inline unsigned int inl(unsigned short port)
> +{
> +	unsigned int val;
> +	asm volatile("inl %w1, %0": "=a"(val) : "Nd" (port));
> +	return val;
> +}
>    

Include guards.

> Index: qemu-kvm/kvm/user/test/x86/time.c
> ===================================================================
> --- /dev/null
> +++ qemu-kvm/kvm/user/test/x86/time.c
> @@ -0,0 +1,1010 @@
> +#include "libcflat.h"
> +#include "apic.h"
> +#include "vm.h"
> +#include "io.h"
> +
> +typedef unsigned char u8;
> +typedef unsigned short u16;
> +typedef unsigned u32;
> +typedef unsigned long ulong;
> +typedef unsigned long long u64;
> +
> +#ifndef ARRAY_SIZE
> +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
> +#endif
> +
> +typedef struct {
> +    unsigned short offset0;
> +    unsigned short selector;
> +    unsigned short ist : 3;
> +    unsigned short : 5;
> +    unsigned short type : 4;
> +    unsigned short : 1;
> +    unsigned short dpl : 2;
> +    unsigned short p : 1;
> +    unsigned short offset1;
> +#ifdef __x86_64__
> +    unsigned offset2;
> +    unsigned reserved;
> +#endif
> +} idt_entry_t;
> +
> +typedef struct {
> +    ulong rflags;
> +    ulong cs;
> +    ulong rip;
> +    ulong func;
> +    ulong regs[sizeof(ulong)*2];
> +} isr_regs_t;
> +
> +#ifdef __x86_64__
> +#  define R "r"
> +#else
> +#  define R "e"
> +#endif
> +
> +extern char isr_entry_point[];
> +
> +asm (
> +    "isr_entry_point: \n"
> +#ifdef __x86_64__
> +    "push %r15 \n\t"
> +    "push %r14 \n\t"
> +    "push %r13 \n\t"
> +    "push %r12 \n\t"
> +    "push %r11 \n\t"
> +    "push %r10 \n\t"
> +    "push %r9  \n\t"
> +    "push %r8  \n\t"
> +#endif
> +    "push %"R "di \n\t"
> +    "push %"R "si \n\t"
> +    "push %"R "bp \n\t"
> +    "push %"R "sp \n\t"
> +    "push %"R "bx \n\t"
> +    "push %"R "dx \n\t"
> +    "push %"R "cx \n\t"
> +    "push %"R "ax \n\t"
> +#ifdef __x86_64__
> +    "mov %rsp, %rdi \n\t"
> +    "callq *8*16(%rsp) \n\t"
> +#else
> +    "push %esp \n\t"
> +    "calll *4+4*8(%esp) \n\t"
> +    "add $4, %esp \n\t"
> +#endif
> +    "pop %"R "ax \n\t"
> +    "pop %"R "cx \n\t"
> +    "pop %"R "dx \n\t"
> +    "pop %"R "bx \n\t"
> +    "pop %"R "bp \n\t"
> +    "pop %"R "bp \n\t"
> +    "pop %"R "si \n\t"
> +    "pop %"R "di \n\t"
> +#ifdef __x86_64__
> +    "pop %r8  \n\t"
> +    "pop %r9  \n\t"
> +    "pop %r10 \n\t"
> +    "pop %r11 \n\t"
> +    "pop %r12 \n\t"
> +    "pop %r13 \n\t"
> +    "pop %r14 \n\t"
> +    "pop %r15 \n\t"
> +#endif
> +#ifdef __x86_64__
> +    "add $8, %rsp \n\t"
> +    "iretq \n\t"
> +#else
> +    "add $4, %esp \n\t"
> +    "iretl \n\t"
> +#endif
> +    );
> +
> +static idt_entry_t idt[256];
> +
> +static int g_fail;
> +static int g_tests;
> +
> +static void report(const char *msg, int pass)
> +{
> +    ++g_tests;
> +    printf("%s: %s\n", msg, (pass ? "PASS" : "FAIL"));
> +    if (!pass)
> +        ++g_fail;
> +}
> +
> +static u16 read_cs(void)
> +{
> +    u16 v;
> +
> +    asm("mov %%cs, %0" : "=rm"(v));
> +    return v;
> +}
> +
> +static void init_idt(void)
> +{
> +    struct {
> +        u16 limit;
> +        ulong idt;
> +    } __attribute__((packed)) idt_ptr = {
> +        sizeof(idt_entry_t) * 256 - 1,
> +        (ulong)&idt,
> +    };
> +
> +    asm volatile("lidt %0" : : "m"(idt_ptr));
> +}
> +
> +static void set_idt_entry(unsigned vec, void (*func)(isr_regs_t *regs))
> +{
> +    u8 *thunk = vmalloc(50);
> +    ulong ptr = (ulong)thunk;
> +    idt_entry_t ent = {
> +        .offset0 = ptr,
> +        .selector = read_cs(),
> +        .ist = 0,
> +        .type = 14,
> +        .dpl = 0,
> +        .p = 1,
> +        .offset1 = ptr>>  16,
> +#ifdef __x86_64__
> +        .offset2 = ptr>>  32,
> +#endif
> +    };
> +#ifdef __x86_64__
> +    /* sub $8, %rsp */
> +    *thunk++ = 0x48; *thunk++ = 0x83; *thunk++ = 0xec; *thunk++ = 0x08;
> +    /* mov $func_low, %(rsp) */
> +    *thunk++ = 0xc7; *thunk++ = 0x04; *thunk++ = 0x24;
> +    *(u32 *)thunk = (ulong)func; thunk += 4;
> +    /* mov $func_high, %(rsp+4) */
> +    *thunk++ = 0xc7; *thunk++ = 0x44; *thunk++ = 0x24; *thunk++ = 0x04;
> +    *(u32 *)thunk = (ulong)func>>  32; thunk += 4;
> +    /* jmp isr_entry_point */
> +    *thunk ++ = 0xe9;
> +    *(u32 *)thunk = (ulong)isr_entry_point - (ulong)(thunk + 4);
> +#else
> +    /* push $func */
> +    *thunk++ = 0x68;
> +    *(u32 *)thunk = (ulong)func;
> +    /* jmp isr_entry_point */
> +    *thunk ++ = 0xe9;
> +    *(u32 *)thunk = (ulong)isr_entry_point - (ulong)(thunk + 4);
> +#endif
> +    idt[vec] = ent;
> +}
> +
> +static void irq_disable(void)
> +{
> +    asm volatile("cli");
> +}
> +
> +static void irq_enable(void)
> +{
> +    asm volatile("sti");
> +}
> +
> +static void eoi(void)
> +{
> +    apic_write(APIC_EOI, 0);
> +}
> +
> +static int ipi_count;
> +
> +static void self_ipi_isr(isr_regs_t *regs)
> +{
> +    ++ipi_count;
> +    eoi();
> +}
> +
> +static void test_self_ipi(void)
> +{
> +    int vec = 0xf1;
> +
> +    set_idt_entry(vec, self_ipi_isr);
> +    irq_enable();
> +    apic_write(APIC_ICR,
> +               APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_FIXED | vec);
> +    asm volatile ("nop");
> +    report("self ipi", ipi_count == 1);
> +}
> +
>    

Needed?

> +static void set_ioapic_redir(unsigned line, unsigned vec, unsigned trig_mode)
> +{
> +    ioapic_redir_entry_t e = {
> +        .vector = vec,
> +        .delivery_mode = 0,
> +        .trig_mode = trig_mode,
> +    };
> +
> +    ioapic_write_redir(line, e);
> +}
> +
> +/* interrupt handlers */
> +
> +#define TIMER_VEC_BASE 0x90
> +
> +struct int_table {
> +    void (*func)(isr_regs_t *regs);
> +    void (*irq_handler)(void *irq_priv);
> +    void *irq_priv;
> +};
> +
> +static struct int_table int_handlers[];
> +
> +#define decl_irq_handler(N)                         \
> +static void timer_int_##N(isr_regs_t *regs) {       \
> +    struct int_table *t =&int_handlers[N];         \
> +    t->irq_handler(t->irq_priv);                    \
> +    eoi();                                          \
> +}
> +
> +void set_irq_handler(int vec, void (*func)(void *irq_priv), void *irq_priv);
> +
> +void hlt(void) { asm volatile("hlt"); }
> +
> +#define NS_FREQ 1000000000ULL
> +#define US_FREQ 1000000ULL
> +
> +#define ns2cyc(ns) (ns*cpu_hz)/NS_FREQ
> +#define cyc2ns(cyc) (cyc*NS_FREQ)/cpu_hz
> +
> +#define us_to_ns(n) (1000*n)
> +#define ms_to_ns(n) (1000000*n)
> +#define s_to_ns(n)  (1000000000*n)
> +
> +#define sdelay(n) nsdelay(s_to_ns(n))
> +
> +u64 cpu_hz;
> +
> +static inline int fls(int x)
> +{
> +        int r;
> +        asm("bsrl %1,%0\n\t"
> +            "jnz 1f\n\t"
> +            "movl $-1,%0\n"
> +            "1:" : "=r" (r) : "rm" (x));
> +        return r + 1;
> +}
> +
> +# define do_div(n,base) ({                                      \
> +        uint32_t __base = (base);                               \
> +        uint32_t __rem;                                         \
> +        __rem = ((uint64_t)(n)) % __base;                       \
> +        (n) = ((uint64_t)(n)) / __base;                         \
> +        __rem;                                                  \
> + })
> +
> +static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
> +{
> +        *remainder = dividend % divisor;
> +        return dividend / divisor;
> +}
> +
> +static inline u64 div_u64(u64 dividend, u32 divisor)
> +{
> +        u32 remainder;
> +        return div_u64_rem(dividend, divisor,&remainder);
> +}
>    

What's wrong with / and %?

> +/* 64bit divisor, dividend and result. dynamic precision */
> +u64 div64_u64(u64 dividend, u64 divisor)
> +{
> +        u32 high, d;
> +
> +        high = divisor>>  32;
> +        if (high) {
> +                unsigned int shift = fls(high);
> +
> +                d = divisor>>  shift;
> +                dividend>>= shift;
> +        } else
> +                d = divisor;
> +
> +        return div_u64(dividend, d);
> +}
>    

Ordinary 64-bit divides should work, no?


-- 
error compiling committee.c: too many arguments to function


  reply	other threads:[~2009-10-08 12:37 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-10-07 19:02 kvm: test: timer testcase Marcelo Tosatti
2009-10-08 12:37 ` Avi Kivity [this message]
2009-10-08 18:02   ` kvm: test: timer testcase (v2) Marcelo Tosatti

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=4ACDDD09.6080302@redhat.com \
    --to=avi@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=mtosatti@redhat.com \
    --cc=zamsden@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.