From patchwork Wed Sep 16 09:25:58 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avi Kivity X-Patchwork-Id: 47894 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n8G9R4fw009775 for ; Wed, 16 Sep 2009 09:27:04 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758343AbZIPJ04 (ORCPT ); Wed, 16 Sep 2009 05:26:56 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S932096AbZIPJ0z (ORCPT ); Wed, 16 Sep 2009 05:26:55 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60889 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758367AbZIPJ0M (ORCPT ); Wed, 16 Sep 2009 05:26:12 -0400 Received: from int-mx03.intmail.prod.int.phx2.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id n8G9QGCc007988 for ; Wed, 16 Sep 2009 05:26:16 -0400 Received: from cleopatra.tlv.redhat.com (cleopatra.tlv.redhat.com [10.35.255.11]) by int-mx03.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id n8G9QD0n003697; Wed, 16 Sep 2009 05:26:15 -0400 Received: from localhost.localdomain (cleopatra.tlv.redhat.com [10.35.255.11]) by cleopatra.tlv.redhat.com (Postfix) with ESMTP id C05E3250ADB; Wed, 16 Sep 2009 12:26:11 +0300 (IDT) From: Avi Kivity To: Marcelo Tosatti Cc: kvm@vger.kernel.org Subject: [PATCH QEMU-KVM 23/34] test: Move apic functions to libcflat Date: Wed, 16 Sep 2009 12:25:58 +0300 Message-Id: <1253093169-1423-24-git-send-email-avi@redhat.com> In-Reply-To: <1253093169-1423-1-git-send-email-avi@redhat.com> References: <1253093169-1423-1-git-send-email-avi@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.16 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Signed-off-by: Avi Kivity --- kvm/user/config-x86-common.mak | 1 + kvm/user/test/{x86/apic.h => lib/x86/apic-defs.h} | 0 kvm/user/test/lib/x86/apic.c | 131 +++++++++++++++++++++ kvm/user/test/lib/x86/apic.h | 33 +++++ kvm/user/test/x86/apic.c | 130 +-------------------- kvm/user/test/x86/cstart64.S | 2 +- 6 files changed, 169 insertions(+), 128 deletions(-) rename kvm/user/test/{x86/apic.h => lib/x86/apic-defs.h} (100%) create mode 100644 kvm/user/test/lib/x86/apic.c create mode 100644 kvm/user/test/lib/x86/apic.h diff --git a/kvm/user/config-x86-common.mak b/kvm/user/config-x86-common.mak index 22a18b2..de9e9e8 100644 --- a/kvm/user/config-x86-common.mak +++ b/kvm/user/config-x86-common.mak @@ -12,6 +12,7 @@ cflatobjs += \ test/lib/x86/smp.o cflatobjs += test/lib/x86/fwcfg.o +cflatobjs += test/lib/x86/apic.o $(libcflat): LDFLAGS += -nostdlib $(libcflat): CFLAGS += -ffreestanding -I test/lib diff --git a/kvm/user/test/x86/apic.h b/kvm/user/test/lib/x86/apic-defs.h similarity index 100% rename from kvm/user/test/x86/apic.h rename to kvm/user/test/lib/x86/apic-defs.h diff --git a/kvm/user/test/lib/x86/apic.c b/kvm/user/test/lib/x86/apic.c new file mode 100644 index 0000000..25517ef --- /dev/null +++ b/kvm/user/test/lib/x86/apic.c @@ -0,0 +1,131 @@ +#include "libcflat.h" +#include "apic.h" + +static void *g_apic = (void *)0xfee00000; +static void *g_ioapic = (void *)0xfec00000; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned u32; +typedef unsigned long ulong; +typedef unsigned long long u64; + +struct apic_ops { + u32 (*reg_read)(unsigned reg); + void (*reg_write)(unsigned reg, u32 val); + void (*icr_write)(u32 val, u32 dest); +}; + +static void outb(unsigned char data, unsigned short port) +{ + asm volatile ("out %0, %1" : : "a"(data), "d"(port)); +} + +static u32 xapic_read(unsigned reg) +{ + return *(volatile u32 *)(g_apic + reg); +} + +static void xapic_write(unsigned reg, u32 val) +{ + *(volatile u32 *)(g_apic + reg) = val; +} + +static void xapic_icr_write(u32 val, u32 dest) +{ + while (xapic_read(APIC_ICR) & APIC_ICR_BUSY) + ; + xapic_write(APIC_ICR2, dest << 24); + xapic_write(APIC_ICR, val); +} + +static const struct apic_ops xapic_ops = { + .reg_read = xapic_read, + .reg_write = xapic_write, + .icr_write = xapic_icr_write, +}; + +static const struct apic_ops *apic_ops = &xapic_ops; + +static u32 x2apic_read(unsigned reg) +{ + unsigned a, d; + + asm volatile ("rdmsr" : "=a"(a), "=d"(d) : "c"(APIC_BASE_MSR + reg/16)); + return a | (u64)d << 32; +} + +static void x2apic_write(unsigned reg, u32 val) +{ + asm volatile ("wrmsr" : : "a"(val), "d"(0), "c"(APIC_BASE_MSR + reg/16)); +} + +static void x2apic_icr_write(u32 val, u32 dest) +{ + asm volatile ("wrmsr" : : "a"(val), "d"(dest), + "c"(APIC_BASE_MSR + APIC_ICR/16)); +} + +static const struct apic_ops x2apic_ops = { + .reg_read = x2apic_read, + .reg_write = x2apic_write, + .icr_write = x2apic_icr_write, +}; + +u32 apic_read(unsigned reg) +{ + return apic_ops->reg_read(reg); +} + +void apic_write(unsigned reg, u32 val) +{ + apic_ops->reg_write(reg, val); +} + +void apic_icr_write(u32 val, u32 dest) +{ + apic_ops->icr_write(val, dest); +} + +#define MSR_APIC_BASE 0x0000001b + +int enable_x2apic(void) +{ + unsigned a, b, c, d; + + asm ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(1)); + + if (c & (1 << 21)) { + asm ("rdmsr" : "=a"(a), "=d"(d) : "c"(MSR_APIC_BASE)); + a |= 1 << 10; + asm ("wrmsr" : : "a"(a), "d"(d), "c"(MSR_APIC_BASE)); + apic_ops = &x2apic_ops; + return 1; + } else { + return 0; + } +} + +void ioapic_write_reg(unsigned reg, u32 value) +{ + *(volatile u32 *)g_ioapic = reg; + *(volatile u32 *)(g_ioapic + 0x10) = value; +} + +void ioapic_write_redir(unsigned line, ioapic_redir_entry_t e) +{ + ioapic_write_reg(0x10 + line * 2 + 0, ((u32 *)&e)[0]); + ioapic_write_reg(0x10 + line * 2 + 1, ((u32 *)&e)[1]); +} + +void enable_apic(void) +{ + printf("enabling apic\n"); + apic_write(0xf0, 0x1ff); /* spurious vector register */ +} + +void mask_pic_interrupts(void) +{ + outb(0xff, 0x21); + outb(0xff, 0xa1); +} diff --git a/kvm/user/test/lib/x86/apic.h b/kvm/user/test/lib/x86/apic.h new file mode 100644 index 0000000..0115ba4 --- /dev/null +++ b/kvm/user/test/lib/x86/apic.h @@ -0,0 +1,33 @@ +#ifndef CFLAT_APIC_H +#define CFLAT_APIC_H + +#include +#include "apic-defs.h" + +typedef struct { + uint8_t vector; + uint8_t delivery_mode:3; + uint8_t dest_mode:1; + uint8_t delivery_status:1; + uint8_t polarity:1; + uint8_t remote_irr:1; + uint8_t trig_mode:1; + uint8_t mask:1; + uint8_t reserve:7; + uint8_t reserved[4]; + uint8_t dest_id; +} ioapic_redir_entry_t; + +void mask_pic_interrupts(void); + +void ioapic_write_redir(unsigned line, ioapic_redir_entry_t e); +void ioapic_write_reg(unsigned reg, uint32_t value); + +void enable_apic(void); +uint32_t apic_read(unsigned reg); +void apic_write(unsigned reg, uint32_t val); +void apic_icr_write(uint32_t val, uint32_t dest); + +int enable_x2apic(void); + +#endif diff --git a/kvm/user/test/x86/apic.c b/kvm/user/test/x86/apic.c index 63d326d..1edfba5 100644 --- a/kvm/user/test/x86/apic.c +++ b/kvm/user/test/x86/apic.c @@ -2,9 +2,6 @@ #include "apic.h" #include "vm.h" -static void *g_apic; -static void *g_ioapic; - typedef unsigned char u8; typedef unsigned short u16; typedef unsigned u32; @@ -103,12 +100,6 @@ static idt_entry_t idt[256]; static int g_fail; static int g_tests; -struct apic_ops { - u32 (*reg_read)(unsigned reg); - void (*reg_write)(unsigned reg, u32 val); - void (*icr_write)(u32 val, u32 dest); -}; - static void outb(unsigned char data, unsigned short port) { asm volatile ("out %0, %1" : : "a"(data), "d"(port)); @@ -122,72 +113,6 @@ static void report(const char *msg, int pass) ++g_fail; } -static u32 xapic_read(unsigned reg) -{ - return *(volatile u32 *)(g_apic + reg); -} - -static void xapic_write(unsigned reg, u32 val) -{ - *(volatile u32 *)(g_apic + reg) = val; -} - -static void xapic_icr_write(u32 val, u32 dest) -{ - while (xapic_read(APIC_ICR) & APIC_ICR_BUSY) - ; - xapic_write(APIC_ICR2, dest << 24); - xapic_write(APIC_ICR, val); -} - -static const struct apic_ops xapic_ops = { - .reg_read = xapic_read, - .reg_write = xapic_write, - .icr_write = xapic_icr_write, -}; - -static const struct apic_ops *apic_ops = &xapic_ops; - -static u32 x2apic_read(unsigned reg) -{ - unsigned a, d; - - asm volatile ("rdmsr" : "=a"(a), "=d"(d) : "c"(APIC_BASE_MSR + reg/16)); - return a | (u64)d << 32; -} - -static void x2apic_write(unsigned reg, u32 val) -{ - asm volatile ("wrmsr" : : "a"(val), "d"(0), "c"(APIC_BASE_MSR + reg/16)); -} - -static void x2apic_icr_write(u32 val, u32 dest) -{ - asm volatile ("wrmsr" : : "a"(val), "d"(dest), - "c"(APIC_BASE_MSR + APIC_ICR/16)); -} - -static const struct apic_ops x2apic_ops = { - .reg_read = x2apic_read, - .reg_write = x2apic_write, - .icr_write = x2apic_icr_write, -}; - -static u32 apic_read(unsigned reg) -{ - return apic_ops->reg_read(reg); -} - -static void apic_write(unsigned reg, u32 val) -{ - apic_ops->reg_write(reg, val); -} - -static void apic_icr_write(u32 val, u32 dest) -{ - apic_ops->icr_write(val, dest); -} - static void test_lapic_existence(void) { u32 lvr; @@ -199,17 +124,9 @@ static void test_lapic_existence(void) #define MSR_APIC_BASE 0x0000001b -static void enable_x2apic(void) +void test_enable_x2apic(void) { - unsigned a, b, c, d; - - asm ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(1)); - - if (c & (1 << 21)) { - asm ("rdmsr" : "=a"(a), "=d"(d) : "c"(MSR_APIC_BASE)); - a |= 1 << 10; - asm ("wrmsr" : : "a"(a), "d"(d), "c"(MSR_APIC_BASE)); - apic_ops = &x2apic_ops; + if (enable_x2apic()) { printf("x2apic enabled\n"); } else { printf("x2apic not detected\n"); @@ -311,32 +228,6 @@ static void test_self_ipi(void) report("self ipi", ipi_count == 1); } -static void ioapic_write_reg(unsigned reg, u32 value) -{ - *(volatile u32 *)g_ioapic = reg; - *(volatile u32 *)(g_ioapic + 0x10) = value; -} - -typedef struct { - u8 vector; - u8 delivery_mode:3; - u8 dest_mode:1; - u8 delivery_status:1; - u8 polarity:1; - u8 remote_irr:1; - u8 trig_mode:1; - u8 mask:1; - u8 reserve:7; - u8 reserved[4]; - u8 dest_id; -} ioapic_redir_entry_t; - -static void ioapic_write_redir(unsigned line, ioapic_redir_entry_t e) -{ - ioapic_write_reg(0x10 + line * 2 + 0, ((u32 *)&e)[0]); - ioapic_write_reg(0x10 + line * 2 + 1, ((u32 *)&e)[1]); -} - static void set_ioapic_redir(unsigned line, unsigned vec) { ioapic_redir_entry_t e = { @@ -410,30 +301,15 @@ static void test_ioapic_simultaneous(void) g_66 && g_78 && g_66_after_78 && g_66_rip == g_78_rip); } -static void enable_apic(void) -{ - printf("enabling apic\n"); - apic_write(0xf0, 0x1ff); /* spurious vector register */ -} - -static void mask_pic_interrupts(void) -{ - outb(0xff, 0x21); - outb(0xff, 0xa1); -} - int main() { setup_vm(); - g_apic = (void *)0xfee00000; - g_ioapic = (void *)0xfec00000; - test_lapic_existence(); mask_pic_interrupts(); enable_apic(); - enable_x2apic(); + test_enable_x2apic(); init_idt(); test_self_ipi(); diff --git a/kvm/user/test/x86/cstart64.S b/kvm/user/test/x86/cstart64.S index 912bcf8..14bb98c 100644 --- a/kvm/user/test/x86/cstart64.S +++ b/kvm/user/test/x86/cstart64.S @@ -1,5 +1,5 @@ -#include "apic.h" +#include "apic-defs.h" boot_idt = 0