From: Nadav Amit <nadav.amit@gmail.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Subject: Re: [kvm-unit-tests PATCH 3/3] x86: Support environments without test-devices
Date: Tue, 2 Jul 2019 23:09:02 -0700 [thread overview]
Message-ID: <567EEA72-611A-444D-9AA5-8218949235E4@gmail.com> (raw)
In-Reply-To: <6bb2a5da-9528-cea9-300a-05d328077201@redhat.com>
> On Jul 2, 2019, at 10:39 PM, Paolo Bonzini <pbonzini@redhat.com> wrote:
>
> On 03/07/19 01:39, Nadav Amit wrote:
>>> On Jul 2, 2019, at 11:28 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
>>>
>>> On 02/07/19 19:45, Nadav Amit wrote:
>>>>>> I know you are not “serious”, but I’ll use this opportunity for a small
>>>>>> clarification. You do need to provide the real number of CPUs as otherwise
>>>>>> things will fail. I do not use cpuid, as my machine, for example has two
>>>>>> sockets. Decoding the ACPI tables is the right way, but I was too lazy to
>>>>>> implement it.
>>>>> What about the mptables, too?
>>>> If you mean to reuse mptable.c from [1] or [2] - I can give it a shot. I am
>>>> not about to write my own parser.
>>>
>>> Sure.
>>
>> So mptable logic works on a couple of my machines, but not all.
>
> Can you send the patch anyway? I can use it as a start for writing a
> MADT parser.
Sure, it could have used some more work… The original code is surprisingly
ugly. Sorry for not doing it myself - but believe me when I tell you that
enabling KVM to run on bare-metal is a misery which already took substantial
of time.
If only I had an ITP things could have been so much easier...
Anyhow, here is the code - it does not really use the number of CPUs, but
just shows it.
-- >8 --
Subject: [PATCH] x86: mptables parsing
Signed-off-by: Nadav Amit <nadav.amit@gmail.com>
---
lib/x86/mptable.c | 220 ++++++++++++++++++++++++++++++++++++++++++++
lib/x86/mptable.h | 6 ++
x86/Makefile.common | 1 +
x86/cstart64.S | 1 +
4 files changed, 228 insertions(+)
create mode 100644 lib/x86/mptable.c
create mode 100644 lib/x86/mptable.h
diff --git a/lib/x86/mptable.c b/lib/x86/mptable.c
new file mode 100644
index 0000000..52ae5cd
--- /dev/null
+++ b/lib/x86/mptable.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 1996, by Steve Passe
+ * All rights reserved.
+ *
+ * hacked to make it work in userspace Linux by Ingo Molnar, same copyright
+ * Re-hacked to make suitable for KVM-unit-tests by Nadav Amit
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "libcflat.h"
+#include "mptable.h"
+
+/* EBDA is @ 40:0e in real-mode terms */
+#define EBDA_POINTER 0x040e /* location of EBDA pointer */
+
+/* CMOS 'top of mem' is @ 40:13 in real-mode terms */
+#define TOPOFMEM_POINTER 0x0413 /* BIOS: base memory size */
+
+#define DEFAULT_TOPOFMEM 0xa0000
+
+#define BIOS_BASE 0xf0000
+#define BIOS_BASE2 0xe0000
+#define BIOS_SIZE 0x10000
+
+#define GROPE_AREA1 0x80000
+#define GROPE_AREA2 0x90000
+#define GROPE_SIZE 0x10000
+
+#define PROCENTRY_FLAG_EN 0x01
+#define PROCENTRY_FLAG_BP 0x02
+
+/* MP Floating Pointer Structure */
+struct mpfps {
+ char signature[4];
+ uint32_t pap;
+ uint8_t length;
+ uint8_t spec_rev;
+ uint8_t checksum;
+ uint8_t mpfb1;
+ uint8_t mpfb2;
+ uint8_t mpfb3;
+ uint8_t mpfb4;
+ uint8_t mpfb5;
+} __attribute__((packed));
+
+struct proc_entry {
+ uint8_t type;
+ uint8_t apicID;
+ uint8_t apicVersion;
+ uint8_t cpuFlags;
+ uint32_t cpuSignature;
+ uint32_t featureFlags;
+ uint32_t reserved1;
+ uint32_t reserved2;
+} __attribute__((packed));
+
+/* MP Configuration Table Header */
+struct mpcth {
+ char signature[4];
+ uint16_t base_table_length;
+ uint8_t spec_rev;
+ uint8_t checksum;
+ uint8_t oem_id[8];
+ uint8_t product_id[12];
+ uint32_t oem_table_pointer;
+ uint16_t oem_table_size;
+ uint16_t entry_count;
+ uint32_t apic_address;
+ uint16_t extended_table_length;
+ uint8_t extended_table_checksum;
+ uint8_t reserved;
+ struct proc_entry entries[0];
+} __attribute__((packed));
+
+static void read_proc_entry(struct proc_entry *entry)
+{
+ int t, family, model;
+
+ printf("#\t%2d", (int) entry->apicID);
+ printf("\t 0x%2x", (unsigned int) entry->apicVersion);
+
+ printf("\t %s, %s",
+ (entry->cpuFlags & PROCENTRY_FLAG_BP) ? "BSP" : "AP",
+ (entry->cpuFlags & PROCENTRY_FLAG_EN) ? "usable" : "unusable");
+
+ t = (int) entry->cpuSignature;
+ family = (t >> 8) & 0xf;
+ model = (t >> 4) & 0xf;
+ if (family == 0xf) {
+ family += (t >> 20) & 0xff;
+ model += (t >> 12) & 0xf0;
+ }
+
+ printf("\t %d\t %d\t %d", family, model, t & 0xf);
+ printf("\t 0x%04x\n", entry->featureFlags);
+}
+
+static int mp_config_table_header(uint32_t pap)
+{
+ struct mpcth *cth = (struct mpcth *)(unsigned long)pap;
+ int c;
+
+ if (!cth) {
+ printf("MP Configuration Table Header MISSING!\n");
+ return 1;
+ }
+
+ /* process all the CPUs */
+ printf("MP Table:\n#\tAPIC ID\tVersion\tState\t\tFamily\tModel\tStep\tFlags\n");
+ for (c = 0; c < cth->entry_count && cth->entries[c].type == 0; c++)
+ read_proc_entry(&cth->entries[c]);
+
+ printf("\n");
+
+ return c;
+}
+
+static struct mpfps *find_signature(unsigned long addr, unsigned int size)
+{
+ struct mpfps *mpfps = (struct mpfps *)addr;
+ const char MP_SIG[]="_MP_";
+ unsigned int i;
+
+ for (i = 0; i < size / sizeof(mpfps); i++) {
+ if (!strncmp(mpfps[i].signature, MP_SIG, 4))
+ return &mpfps[i];
+ }
+ return NULL;
+}
+
+struct mem_location {
+ unsigned long addr;
+ unsigned long size;
+};
+
+const struct mem_location acpi_locations[] = {
+ { DEFAULT_TOPOFMEM - 1024, 1024 },
+ { BIOS_BASE, BIOS_SIZE },
+ { BIOS_BASE2, BIOS_SIZE },
+ { GROPE_AREA1, GROPE_SIZE },
+ { GROPE_AREA2, GROPE_SIZE },
+ { 0, 0 }
+};
+
+static struct mpfps *apic_probe(void)
+{
+ const struct mem_location *loc = acpi_locations;
+ uint16_t segment;
+ unsigned long target;
+ struct mpfps *mpfps;
+
+ /* search Extended Bios Data Area, if present */
+ segment = *(uint16_t *)EBDA_POINTER;
+
+ if (segment == 0)
+ return NULL;
+
+ printf("\nEBDA points to: %x\n", segment);
+
+ target = (unsigned long)segment << 4;
+ printf("EBDA segment ptr: %lx\n", target);
+
+ mpfps = find_signature(target, 1024);
+ if (mpfps)
+ return mpfps;
+
+ /* read CMOS for real top of mem */
+ segment = *(uint16_t *)TOPOFMEM_POINTER;
+ --segment; /* less ONE_KBYTE */
+ target = segment * 1024;
+
+ mpfps = find_signature(target, 1024);
+ if (mpfps)
+ return mpfps;
+
+ for (loc = acpi_locations; loc->addr != 0; loc++) {
+ mpfps = find_signature(loc->addr, loc->size);
+ if (mpfps)
+ return mpfps;
+ }
+
+ return NULL;
+}
+
+int enumerate_cpus(void)
+{
+ struct mpfps *mpfps;
+
+ /* probe for MP structures */
+ mpfps = apic_probe();
+ if (mpfps == NULL) {
+ printf("Could not find MP structures\n");
+ return 1;
+ }
+
+ /* check whether an MP config table exists */
+ if (mpfps->mpfb1)
+ return 1;
+
+ return mp_config_table_header(mpfps->pap);
+}
diff --git a/lib/x86/mptable.h b/lib/x86/mptable.h
new file mode 100644
index 0000000..c4fd098
--- /dev/null
+++ b/lib/x86/mptable.h
@@ -0,0 +1,6 @@
+#ifndef CFLAT_MPTABLE_H
+#define CFLAT_MPTABLE_H
+
+int enumerate_cpus(void);
+
+#endif
diff --git a/x86/Makefile.common b/x86/Makefile.common
index e612dbe..137e6d5 100644
--- a/x86/Makefile.common
+++ b/x86/Makefile.common
@@ -21,6 +21,7 @@ cflatobjs += lib/x86/acpi.o
cflatobjs += lib/x86/stack.o
cflatobjs += lib/x86/fault_test.o
cflatobjs += lib/x86/delay.o
+cflatobjs += lib/x86/mptable.o
OBJDIRS += lib/x86
diff --git a/x86/cstart64.S b/x86/cstart64.S
index cc7926a..0844b2a 100644
--- a/x86/cstart64.S
+++ b/x86/cstart64.S
@@ -247,6 +247,7 @@ start64:
mov mb_boot_info(%rip), %rbx
mov %rbx, %rdi
call setup_multiboot
+ call enumerate_cpus
call setup_libcflat
mov mb_cmdline(%rbx), %eax
mov %rax, __args(%rip)
--
2.17.1
next prev parent reply other threads:[~2019-07-03 6:09 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-06-28 20:30 [kvm-unit-tests PATCH 0/3] x86: Running tests on bare-metal Nadav Amit
2019-06-28 20:30 ` [kvm-unit-tests PATCH 1/3] libcflat: use stdbool Nadav Amit
2019-07-02 16:08 ` Paolo Bonzini
2019-06-28 20:30 ` [kvm-unit-tests PATCH 2/3] x86/vmx: Use plus for positive filters Nadav Amit
2019-06-28 20:30 ` [kvm-unit-tests PATCH 3/3] x86: Support environments without test-devices Nadav Amit
2019-07-02 16:08 ` Paolo Bonzini
2019-07-02 16:43 ` Nadav Amit
2019-07-02 17:24 ` Paolo Bonzini
2019-07-02 17:45 ` Nadav Amit
2019-07-02 18:28 ` Paolo Bonzini
2019-07-02 23:39 ` Nadav Amit
2019-07-02 23:56 ` Nadav Amit
2019-07-03 5:39 ` Paolo Bonzini
2019-07-03 6:09 ` Nadav Amit [this message]
2019-07-15 15:48 ` Andrew Jones
2019-07-15 18:08 ` Nadav Amit
2019-07-15 18:26 ` Paolo Bonzini
2019-07-15 18:43 ` Nadav Amit
2019-07-15 18:54 ` Paolo Bonzini
2019-07-21 16:40 ` Nadav Amit
2019-07-21 16:51 ` Paolo Bonzini
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=567EEA72-611A-444D-9AA5-8218949235E4@gmail.com \
--to=nadav.amit@gmail.com \
--cc=kvm@vger.kernel.org \
--cc=pbonzini@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).