kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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

  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).