From: Jerone Young <jyoung5@us.ibm.com>
To: kvm@vger.kernel.org
Cc: kvm-ppc@vger.kernel.org
Subject: [PATCH 1 of 4] Consilidate libcflat for x86 to single lib for all archs
Date: Wed, 25 Jun 2008 15:39:11 -0500 [thread overview]
Message-ID: <2f006fe45fbf14496b0e.1214426351@thinkpadL> (raw)
In-Reply-To: <patchbomb.1214426350@thinkpadL>
8 files changed, 453 insertions(+)
user/test/lib/libcflat.h | 37 +++++++++
user/test/lib/panic.c | 13 +++
user/test/lib/printf.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++
user/test/lib/string.c | 21 +++++
user/test/lib/x86/apic.h | 14 +++
user/test/lib/x86/io.c | 23 +++++
user/test/lib/x86/smp.c | 150 ++++++++++++++++++++++++++++++++++++++
user/test/lib/x86/smp.h | 16 ++++
This patch lays the ground work for a sinlge libcflat library that can be used for x86. But this allows for other archs to share common code, and build a single archive for tests to use libcflat functions.
Signed-off-by: Jerone Young <jyoung5@.us.com>
diff --git a/user/test/lib/libcflat.h b/user/test/lib/libcflat.h
new file mode 100644
--- /dev/null
+++ b/user/test/lib/libcflat.h
@@ -0,0 +1,37 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#ifndef __LIBCFLAT_H
+#define __LIBCFLAT_H
+
+#include <stdarg.h>
+
+extern int main(void);
+extern void exit(int code);
+extern void panic(char *fmt, ...);
+
+extern unsigned long strlen(const char *buf);
+extern char *strcat(char *dest, const char *src);
+
+extern int printf(const char *fmt, ...);
+extern int vsnprintf(char *buf, int size, const char *fmt, va_list va);
+
+extern void puts(const char *s);
+
+#endif
diff --git a/user/test/lib/panic.c b/user/test/lib/panic.c
new file mode 100644
--- /dev/null
+++ b/user/test/lib/panic.c
@@ -0,0 +1,13 @@
+#include "libcflat.h"
+
+void panic(char *fmt, ...)
+{
+ va_list va;
+ char buf[2000];
+
+ va_start(va, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, va);
+ va_end(va);
+ puts(buf);
+ exit(-1);
+}
diff --git a/user/test/lib/printf.c b/user/test/lib/printf.c
new file mode 100644
--- /dev/null
+++ b/user/test/lib/printf.c
@@ -0,0 +1,179 @@
+#include "libcflat.h"
+
+typedef struct pstream {
+ char *buffer;
+ int remain;
+ int added;
+} pstream_t;
+
+static void addchar(pstream_t *p, char c)
+{
+ if (p->remain) {
+ *p->buffer++ = c;
+ --p->remain;
+ }
+ ++p->added;
+}
+
+void print_str(pstream_t *p, const char *s)
+{
+ while (*s)
+ addchar(p, *s++);
+}
+
+static char digits[16] = "0123456789abcdef";
+
+void print_int(pstream_t *ps, long long n, int base)
+{
+ char buf[sizeof(long) * 3 + 2], *p = buf;
+ int s = 0, i;
+
+ if (n < 0) {
+ n = -n;
+ s = 1;
+ }
+
+ while (n) {
+ *p++ = digits[n % base];
+ n /= base;
+ }
+
+ if (s)
+ *p++ = '-';
+
+ if (p == buf)
+ *p++ = '0';
+
+ for (i = 0; i < (p - buf) / 2; ++i) {
+ char tmp;
+
+ tmp = buf[i];
+ buf[i] = p[-1-i];
+ p[-1-i] = tmp;
+ }
+
+ *p = 0;
+
+ print_str(ps, buf);
+}
+
+void print_unsigned(pstream_t *ps, unsigned long long n, int base)
+{
+ char buf[sizeof(long) * 3 + 1], *p = buf;
+ int i;
+
+ while (n) {
+ *p++ = digits[n % base];
+ n /= base;
+ }
+
+ if (p == buf)
+ *p++ = '0';
+
+ for (i = 0; i < (p - buf) / 2; ++i) {
+ char tmp;
+
+ tmp = buf[i];
+ buf[i] = p[-1-i];
+ p[-1-i] = tmp;
+ }
+
+ *p = 0;
+
+ print_str(ps, buf);
+}
+
+int vsnprintf(char *buf, int size, const char *fmt, va_list va)
+{
+ pstream_t s;
+
+ s.buffer = buf;
+ s.remain = size - 1;
+ s.added = 0;
+ while (*fmt) {
+ char f = *fmt++;
+ int nlong = 0;
+
+ if (f != '%') {
+ addchar(&s, f);
+ continue;
+ }
+ morefmt:
+ f = *fmt++;
+ switch (f) {
+ case '%':
+ addchar(&s, '%');
+ break;
+ case '\0':
+ --fmt;
+ break;
+ case 'l':
+ ++nlong;
+ goto morefmt;
+ case 'd':
+ switch (nlong) {
+ case 0:
+ print_int(&s, va_arg(va, int), 10);
+ break;
+ case 1:
+ print_int(&s, va_arg(va, long), 10);
+ break;
+ default:
+ print_int(&s, va_arg(va, long long), 10);
+ break;
+ }
+ break;
+ case 'x':
+ switch (nlong) {
+ case 0:
+ print_unsigned(&s, va_arg(va, unsigned), 16);
+ break;
+ case 1:
+ print_unsigned(&s, va_arg(va, unsigned long), 16);
+ break;
+ default:
+ print_unsigned(&s, va_arg(va, unsigned long long), 16);
+ break;
+ }
+ break;
+ case 'p':
+ print_str(&s, "0x");
+ print_unsigned(&s, (unsigned long)va_arg(va, void *), 16);
+ break;
+ case 's':
+ print_str(&s, va_arg(va, const char *));
+ break;
+ default:
+ addchar(&s, f);
+ break;
+ }
+ }
+ *s.buffer = 0;
+ ++s.added;
+ return s.added;
+}
+
+
+int snprintf(char *buf, int size, const char *fmt, ...)
+{
+ va_list va;
+ int r;
+
+ va_start(va, fmt);
+ r = vsnprintf(buf, size, fmt, va);
+ va_end(va);
+ return r;
+}
+
+int printf(const char *fmt, ...)
+{
+ va_list va;
+ char buf[2000];
+ int r;
+
+ va_start(va, fmt);
+ r = vsnprintf(buf, sizeof buf, fmt, va);
+ va_end(va);
+ puts(buf);
+ return r;
+}
diff --git a/user/test/lib/string.c b/user/test/lib/string.c
new file mode 100644
--- /dev/null
+++ b/user/test/lib/string.c
@@ -0,0 +1,21 @@
+#include "libcflat.h"
+
+unsigned long strlen(const char *buf)
+{
+ unsigned long len = 0;
+
+ while (*buf++)
+ ++len;
+ return len;
+}
+
+char *strcat(char *dest, const char *src)
+{
+ char *p = dest;
+
+ while (*p)
+ ++p;
+ while ((*p++ = *src++) != 0)
+ ;
+ return dest;
+}
diff --git a/user/test/lib/x86/apic.h b/user/test/lib/x86/apic.h
new file mode 100644
--- /dev/null
+++ b/user/test/lib/x86/apic.h
@@ -0,0 +1,14 @@
+#ifndef SILLY_APIC_H
+#define SILLY_APIC_H
+
+#define APIC_BASE 0x1000
+#define APIC_SIZE 0x100
+
+#define APIC_REG_NCPU 0x00
+#define APIC_REG_ID 0x04
+#define APIC_REG_SIPI_ADDR 0x08
+#define APIC_REG_SEND_SIPI 0x0c
+#define APIC_REG_IPI_VECTOR 0x10
+#define APIC_REG_SEND_IPI 0x14
+
+#endif
diff --git a/user/test/lib/x86/io.c b/user/test/lib/x86/io.c
new file mode 100644
--- /dev/null
+++ b/user/test/lib/x86/io.c
@@ -0,0 +1,23 @@
+#include <libcflat.h>
+#include "smp.h"
+
+static struct spinlock lock;
+
+static void print_serial(const char *buf)
+{
+ unsigned long len = strlen(buf);
+
+ asm volatile ("rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1));
+}
+
+void puts(const char *s)
+{
+ spin_lock(&lock);
+ print_serial(s);
+ spin_unlock(&lock);
+}
+
+void exit(int code)
+{
+ asm volatile("out %0, %1" : : "a"(code), "d"((short)0xf4));
+}
diff --git a/user/test/lib/x86/smp.c b/user/test/lib/x86/smp.c
new file mode 100644
--- /dev/null
+++ b/user/test/lib/x86/smp.c
@@ -0,0 +1,150 @@
+
+#include <libcflat.h>
+#include "smp.h"
+#include "apic.h"
+
+#define IPI_VECTOR 0x20
+
+static int apic_read(int reg)
+{
+ unsigned short port = APIC_BASE + reg;
+ unsigned v;
+
+ asm volatile ("in %1, %0" : "=a"(v) : "d"(port));
+ return v;
+}
+
+static void apic_write(int reg, unsigned v)
+{
+ unsigned short port = APIC_BASE + reg;
+
+ asm volatile ("out %0, %1" : : "a"(v), "d"(port));
+}
+
+static int apic_get_cpu_count()
+{
+ return apic_read(APIC_REG_NCPU);
+}
+
+static int apic_get_id()
+{
+ return apic_read(APIC_REG_ID);
+}
+
+static void apic_set_ipi_vector(int vector)
+{
+ apic_write(APIC_REG_IPI_VECTOR, vector);
+}
+
+static void apic_send_ipi(int cpu)
+{
+ apic_write(APIC_REG_SEND_IPI, cpu);
+}
+
+static struct spinlock ipi_lock;
+static void (*ipi_function)(void *data);
+static void *ipi_data;
+static volatile int ipi_done;
+
+static __attribute__((used)) void ipi()
+{
+ ipi_function(ipi_data);
+ ipi_done = 1;
+}
+
+asm (
+ "ipi_entry: \n"
+ " call ipi \n"
+#ifndef __x86_64__
+ " iret"
+#else
+ " iretq"
+#endif
+ );
+
+
+static void set_ipi_descriptor(void (*ipi_entry)(void))
+{
+ unsigned short *desc = (void *)(IPI_VECTOR * sizeof(long) * 2);
+ unsigned short cs;
+ unsigned long ipi = (unsigned long)ipi_entry;
+
+ asm ("mov %%cs, %0" : "=r"(cs));
+ desc[0] = ipi;
+ desc[1] = cs;
+ desc[2] = 0x8e00;
+ desc[3] = ipi >> 16;
+#ifdef __x86_64__
+ desc[4] = ipi >> 32;
+ desc[5] = ipi >> 48;
+ desc[6] = 0;
+ desc[7] = 0;
+#endif
+}
+
+void spin_lock(struct spinlock *lock)
+{
+ int v = 1;
+
+ do {
+ asm volatile ("xchg %1, %0" : "+m"(lock->v), "+r"(v));
+ } while (v);
+ asm volatile ("" : : : "memory");
+}
+
+void spin_unlock(struct spinlock *lock)
+{
+ asm volatile ("" : : : "memory");
+ lock->v = 0;
+}
+
+int cpu_count(void)
+{
+ return apic_get_cpu_count();
+}
+
+int smp_id(void)
+{
+ return apic_get_id();
+}
+
+void on_cpu(int cpu, void (*function)(void *data), void *data)
+{
+ spin_lock(&ipi_lock);
+ if (cpu == apic_get_id())
+ function(data);
+ else {
+ ipi_function = function;
+ ipi_data = data;
+ apic_send_ipi(cpu);
+ while (!ipi_done)
+ ;
+ ipi_done = 0;
+ }
+ spin_unlock(&ipi_lock);
+}
+
+static void (*smp_main_func)(void);
+static volatile int smp_main_running;
+
+asm ("smp_init_entry: \n"
+ "incl smp_main_running \n"
+ "sti \n"
+ "call *smp_main_func");
+
+void smp_init(void (*smp_main)(void))
+{
+ int i;
+ void smp_init_entry(void);
+ void ipi_entry(void);
+
+ apic_set_ipi_vector(IPI_VECTOR);
+ set_ipi_descriptor(smp_init_entry);
+ smp_main_func = smp_main;
+ for (i = 1; i < cpu_count(); ++i) {
+ apic_send_ipi(i);
+ while (smp_main_running < i)
+ ;
+ }
+ set_ipi_descriptor(ipi_entry);
+}
diff --git a/user/test/lib/x86/smp.h b/user/test/lib/x86/smp.h
new file mode 100644
--- /dev/null
+++ b/user/test/lib/x86/smp.h
@@ -0,0 +1,16 @@
+#ifndef __SMP_H
+#define __SMP_H
+
+struct spinlock {
+ int v;
+};
+
+void smp_init(void (*smp_main)(void));
+
+int cpu_count(void);
+int smp_id(void);
+void on_cpu(int cpu, void (*function)(void *data), void *data);
+void spin_lock(struct spinlock *lock);
+void spin_unlock(struct spinlock *lock);
+
+#endif
next prev parent reply other threads:[~2008-06-25 20:41 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-06-25 20:39 [PATCH 0 of 4] [kvm-userspace][test] consolidate test libs to libcflat Jerone Young
2008-06-25 20:39 ` Jerone Young [this message]
2008-06-25 20:39 ` [PATCH 2 of 4] Add Makefile and test changes required for x86 to use libcflat Jerone Young
2008-06-25 20:39 ` [PATCH 3 of 4] Remove old x86 test libs, that are now appart of libcflat Jerone Young
2008-06-25 20:39 ` [PATCH 4 of 4] Add initial PowerPC libcflat files & make file changes Jerone Young
2008-06-25 21:28 ` Hollis Blanchard
2008-06-26 15:14 ` Jerone Young
2008-06-25 21:27 ` [PATCH 0 of 4] [kvm-userspace][test] consolidate test libs to libcflat Hollis Blanchard
2008-06-26 15:12 ` Jerone Young
2008-06-26 22:01 ` Hollis Blanchard
2008-06-29 9:10 ` Avi Kivity
2008-06-29 13:24 ` Avi Kivity
2008-07-01 7:33 ` Jerone Young
2008-07-05 9:28 ` Avi Kivity
2008-07-05 17:32 ` Jerone Young
2008-07-05 17:36 ` Avi Kivity
2008-07-05 17:59 ` Jerone Young
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=2f006fe45fbf14496b0e.1214426351@thinkpadL \
--to=jyoung5@us.ibm.com \
--cc=kvm-ppc@vger.kernel.org \
--cc=kvm@vger.kernel.org \
/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