Re: [kvm-unit-tests PATCH 3/3] x86: Support environments without test-devices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> On Jul 2, 2019, at 10:39 PM, Paolo Bonzini <pbonzini@xxxxxxxxxx> wrote:
> 
> On 03/07/19 01:39, Nadav Amit wrote:
>>> On Jul 2, 2019, at 11:28 AM, Paolo Bonzini <pbonzini@xxxxxxxxxx> 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@xxxxxxxxx>
---
 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



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux