kvm.vger.kernel.org archive mirror
 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 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).