[LinuxBIOS] r418 - in LinuxBIOSv3: arch/x86 device include include/arch/x86 include/arch/x86/arch include/device lib util/dtc

svn at openbios.org svn at openbios.org
Fri Jun 29 18:57:23 CEST 2007


Author: stepan
Date: 2007-06-29 18:57:23 +0200 (Fri, 29 Jun 2007)
New Revision: 418

Added:
   LinuxBIOSv3/include/arch/x86/arch/elf.h
   LinuxBIOSv3/include/arch/x86/arch/spinlock.h
Removed:
   LinuxBIOSv3/include/arch/x86/archelf.h
   LinuxBIOSv3/include/stdlib.h
   LinuxBIOSv3/lib/malloc.c
Modified:
   LinuxBIOSv3/arch/x86/Kconfig
   LinuxBIOSv3/arch/x86/Makefile
   LinuxBIOSv3/arch/x86/stage1.c
   LinuxBIOSv3/device/device.c
   LinuxBIOSv3/include/device/device.h
   LinuxBIOSv3/include/elf.h
   LinuxBIOSv3/lib/console.c
   LinuxBIOSv3/util/dtc/dtc-parser.y
Log:
* start using arch/foo.h again instead of archfoo.h (trivial)
* make constructor an initializer.
* fix memory leak/code flow error in current code
* add spinlocking
* drop malloc and use new_device for device allocation instead.
* add CONFIG_SMP as it is needed by spinlocks and soon other stuff.

Signed-off-by: Stefan Reinauer <stepan at coresystems.de>
Acked-by: Ronald G. Minnich <rminnich at gmail.com>



Modified: LinuxBIOSv3/arch/x86/Kconfig
===================================================================
--- LinuxBIOSv3/arch/x86/Kconfig	2007-06-29 15:32:19 UTC (rev 417)
+++ LinuxBIOSv3/arch/x86/Kconfig	2007-06-29 16:57:23 UTC (rev 418)
@@ -55,3 +55,11 @@
 	  a battery backed up real time clock with CMOS NVRAM.
 	  It is usually set in mainboard/*/Kconfig.
 
+config SMP
+	boolean
+	help
+	  This option is used to enable certain functions to make 
+	  LinuxBIOS work correctly on symmetric multi processor
+	  systems.
+	  It is usually set in mainboard/*/Kconfig.
+ 

Modified: LinuxBIOSv3/arch/x86/Makefile
===================================================================
--- LinuxBIOSv3/arch/x86/Makefile	2007-06-29 15:32:19 UTC (rev 417)
+++ LinuxBIOSv3/arch/x86/Makefile	2007-06-29 16:57:23 UTC (rev 418)
@@ -123,8 +123,7 @@
 # TODO: This should be compressed with the default compressor.
 #
 
-STAGE2_LIB_OBJ       = stage2.o clog2.o mem.o malloc.o tables.o delay.o \
-		       compute_ip_checksum.o
+STAGE2_LIB_OBJ       = stage2.o clog2.o mem.o tables.o delay.o compute_ip_checksum.o
 
 STAGE2_ARCH_X86_OBJ  = archtables.o linuxbios_table.o udelay_io.o
 STAGE2_ARCH_X86_OBJ += pci_ops_auto.o pci_ops_conf1.o pci_ops_conf2.o

Modified: LinuxBIOSv3/arch/x86/stage1.c
===================================================================
--- LinuxBIOSv3/arch/x86/stage1.c	2007-06-29 15:32:19 UTC (rev 417)
+++ LinuxBIOSv3/arch/x86/stage1.c	2007-06-29 16:57:23 UTC (rev 418)
@@ -119,12 +119,15 @@
 	if (ret)
 		die("Failed RAM init code\n");
 
-	printk(BIOS_INFO, "Done RAM init code\n");
-	/* this is nasty. And, it has to be done this way. Sorry! */
-	/* we have to turn off CAR, and do some other things, and it has to be done
-	 * inline -- you can't call a function
-	 */
+	printk(BIOS_DEBUG, "Done RAM init code\n");
 
+
+	/* Turn off Cache-As-Ram, and do some other things.
+	 *
+	 * This has to be done inline -- You can't call a function because the
+	 * return stack does not survive.
+ 	 */
+ 
         __asm__ volatile (
 	/* 
 	FIXME : backup stack in CACHE_AS_RAM into mmx and sse and after we get STACK up, we restore that.

Modified: LinuxBIOSv3/device/device.c
===================================================================
--- LinuxBIOSv3/device/device.c	2007-06-29 15:32:19 UTC (rev 417)
+++ LinuxBIOSv3/device/device.c	2007-06-29 16:57:23 UTC (rev 418)
@@ -10,8 +10,9 @@
  * Copyright (C) 2003 Ronald G. Minnich <rminnich at gmail.com>
  * Copyright (C) 2004-2005 Li-Ta Lo <ollie at lanl.gov>
  * Copyright (C) 2005-2006 Tyan
- * (Written by Yinghai Lu <yhlu at tyan.com> for Tyan)
+ * (Written by Yinghai Lu for Tyan)
  * Copyright (C) 2005-2006 Stefan Reinauer <stepan at openbios.org>
+ * Copyright (C) 2007 coresystems GmbH
  */
 
 /*
@@ -34,10 +35,8 @@
 #include <device/pci.h>
 #include <device/pci_ids.h>
 #include <string.h>
-#include <stdlib.h>
 #include <lib.h>
-#warning Do we need spinlocks in device/device.c?
-//#include <smp/spinlock.h>
+#include <spinlock.h>
 
 /** Linked list of all devices. */
 struct device *all_devices = &dev_root;
@@ -61,6 +60,34 @@
 #define DEVICE_IO_START 0x1000
 
 /**
+ * device memory. All the device tree wil live here
+ */
+
+#define MAX_DEVICES 256
+static struct device devs[MAX_DEVICES];
+
+/**
+ * The device creator.
+ * 
+ * reserves a piece of memory for a device in the tree
+ *
+ * @return Pointer to the newly created device structure.
+ */
+
+static struct device *new_device(void)
+{
+	static int devcnt=0;
+	devcnt++;
+
+	/* Should we really die here? */
+	if (devcnt>=MAX_DEVICES) {
+		die("Too many devices. Increase MAX_DEVICES\n");
+	}
+
+	return &devs[devcnt];
+}
+
+/**
  * Initialization tasks for the device tree code. 
  * 
  * At present, merely sets up last_dev_p, which used to be done by
@@ -76,27 +103,17 @@
 }
 
 /**
- * The default constructor, which simply allocates and sets the ops pointer.
+ * The default constructor, which simply sets the ops pointer.
  * 
- * Allocate a new device structure and initialize device->ops. 
+ * Initialize device->ops of a newly allocated device structure.
  *
+ * @param dev Pointer to the newly created device structure.
  * @param constructor A pointer to a struct constructor.
- * @return Pointer to the newly created device structure.
  */
-struct device *default_device_constructor(struct constructor *constructor)
+void default_device_constructor(struct device *dev, struct constructor *constructor)
 {
-	struct device *dev;
-	dev = malloc(sizeof(*dev));
-
-	// FIXME: This is overkill. Our malloc() will never return with 
-	// a return value of NULL. So this is dead code (and thus would
-	// drop code coverage and usability in safety critical environments.
-	if (dev == NULL) {
-		die("DEV: out of memory.\n");
-	}
-	memset(dev, 0, sizeof(dev));
+	printk(BIOS_DEBUG, "default device constructor called\n");
 	dev->ops = constructor->ops;
-	return dev;
 }
 
 /**
@@ -119,9 +136,6 @@
 			printk(BIOS_SPEW, "%s: cons 0x%lx, cons id %s\n",
 			       __func__, c, dev_id_string(&c->id));
 			if ((!c->ops) || (!c->ops->constructor)) {
-				printk(BIOS_INFO,
-				       "Constructor for %s with missing ops or ops->constructor!\n",
-				       dev_id_string(&c->id));
 				continue;
 			}
 			if (id_eq(&c->id, id)) {
@@ -131,7 +145,7 @@
 		}
 	}
 
-	return 0;
+	return NULL;
 }
 
 /**
@@ -141,23 +155,22 @@
  * Call that constructor via constructor->ops->constructor, with itself as
  * a parameter; return the result. 
  *
+ * @param dev  Pointer to the newly created device structure.
  * @param path Path to the device to be created.
- * @return Pointer to the newly created device structure.
  * @see device_path
  */
-struct device *constructor(struct device_id *id)
+void constructor(struct device *dev, struct device_id *id)
 {
 	struct constructor *c;
-	struct device *dev = 0;
 
 	c = find_constructor(id);
-	printk(BIOS_DEBUG, "%s constructor is 0x%lx\n", __func__, c);
-	if (!c)
-		return 0;
-
-	dev = c->ops->constructor(c);
-	printk(BIOS_DEBUG, "%s returns 0x%lx\n", __func__, dev);
-	return dev;
+	printk(BIOS_SPEW, "%s: constructor is 0x%lx\n", __func__, c);
+ 
+	if(c && c->ops && c->ops->constructor)
+		c->ops->constructor(dev, c);
+	else
+		printk(BIOS_INFO, "No constructor called for %s.\n", 
+			dev_id_string(&c->id));
 }
 
 /**
@@ -177,24 +190,18 @@
 	struct device *dev, *child;
 	int link;
 
-//      spin_lock(&dev_lock);
+	spin_lock(&dev_lock);
 
 	/* Find the last child of our parent. */
 	for (child = parent->children; child && child->sibling; /* */) {
 		child = child->sibling;
 	}
 
-	dev = constructor(devid);
-	if (!dev)
-		printk(BIOS_DEBUG, "%s: No constructor, going with empty dev",
-		       dev_id_string(devid));
+	dev = new_device();
+	if (!dev) /* Please don't do this at home */
+		goto out;
 
-	dev = malloc(sizeof(*dev));
-	if (dev == NULL) {
-		die("DEV: out of memory.\n");
-	}
 	memset(dev, 0, sizeof(*dev));
-
 	memcpy(&dev->path, path, sizeof(*path));
 
 	/* Initialize the back pointers in the link fields. */
@@ -223,7 +230,14 @@
 	/* Give the device a name. */
 	sprintf(dev->dtsname, "dynamic %s", dev_path(dev));
 
-	// spin_unlock(&dev_lock);
+	/* Run the device specific constructor as last part of the chain
+	 * so it gets the chance to overwrite the "inherited" values above
+	 */
+
+	constructor(dev, devid);
+
+out:
+	spin_unlock(&dev_lock);
 	return dev;
 }
 

Copied: LinuxBIOSv3/include/arch/x86/arch/elf.h (from rev 417, LinuxBIOSv3/include/arch/x86/archelf.h)
===================================================================
--- LinuxBIOSv3/include/arch/x86/arch/elf.h	                        (rev 0)
+++ LinuxBIOSv3/include/arch/x86/arch/elf.h	2007-06-29 16:57:23 UTC (rev 418)
@@ -0,0 +1,8 @@
+#ifndef ARCH_ELF_H
+#define ARCH_ELF_H
+
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA	ELFDATA2LSB
+#define ELF_ARCH	EM_386
+
+#endif /* ARCH_ELF_H */

Added: LinuxBIOSv3/include/arch/x86/arch/spinlock.h
===================================================================
--- LinuxBIOSv3/include/arch/x86/arch/spinlock.h	                        (rev 0)
+++ LinuxBIOSv3/include/arch/x86/arch/spinlock.h	2007-06-29 16:57:23 UTC (rev 418)
@@ -0,0 +1,83 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2001 Linux Networx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef ARCH_SPINLOCK_H
+#define ARCH_SPINLOCK_H
+
+/*
+ * Your basic SMP spinlocks, allowing only a single CPU anywhere
+ */
+
+typedef struct {
+	volatile unsigned int lock;
+} spinlock_t;
+
+
+#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 }
+
+/*
+ * Simple spin lock operations.  There are two variants, one clears IRQ's
+ * on the local processor, one does not.
+ *
+ * We make no fairness assumptions. They have a cost.
+ */
+#define barrier() __asm__ __volatile__("": : :"memory")
+#define spin_is_locked(x)	(*(volatile char *)(&(x)->lock) <= 0)
+#define spin_unlock_wait(x)	do { barrier(); } while(spin_is_locked(x))
+
+#define spin_lock_string \
+	"\n1:\t" \
+	"lock ; decb %0\n\t" \
+	"js 2f\n" \
+	".section .text.lock,\"ax\"\n" \
+	"2:\t" \
+	"cmpb $0,%0\n\t" \
+	"rep;nop\n\t" \
+	"jle 2b\n\t" \
+	"jmp 1b\n" \
+	".previous"
+
+/*
+ * This works. Despite all the confusion.
+ */
+#define spin_unlock_string \
+	"movb $1,%0"
+
+static inline __attribute__((always_inline)) void spin_lock(spinlock_t *lock)
+{
+	__asm__ __volatile__(
+		spin_lock_string
+		:"=m" (lock->lock) : : "memory");
+}
+
+static inline __attribute__((always_inline)) void spin_unlock(spinlock_t *lock)
+{
+	__asm__ __volatile__(
+		spin_unlock_string
+		:"=m" (lock->lock) : : "memory");
+}
+
+/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+static inline __attribute__((always_inline)) void cpu_relax(void)
+{
+	__asm__ __volatile__("rep;nop": : :"memory");
+}
+
+#endif /* ARCH_SPINLOCK_H */

Deleted: LinuxBIOSv3/include/arch/x86/archelf.h
===================================================================
--- LinuxBIOSv3/include/arch/x86/archelf.h	2007-06-29 15:32:19 UTC (rev 417)
+++ LinuxBIOSv3/include/arch/x86/archelf.h	2007-06-29 16:57:23 UTC (rev 418)
@@ -1,8 +0,0 @@
-#ifndef ARCH_X86_ARCHELF_H
-#define ARCH_X86_ARCHELF_H
-
-#define ELF_CLASS	ELFCLASS32
-#define ELF_DATA	ELFDATA2LSB
-#define ELF_ARCH	EM_386
-
-#endif /* ARCH_X86_ARCHELF_H */

Modified: LinuxBIOSv3/include/device/device.h
===================================================================
--- LinuxBIOSv3/include/device/device.h	2007-06-29 15:32:19 UTC (rev 417)
+++ LinuxBIOSv3/include/device/device.h	2007-06-29 16:57:23 UTC (rev 418)
@@ -112,18 +112,21 @@
 	void (*set_link)(struct device * dev, unsigned int link);
 	void (*reset_bus)(struct bus *bus);
 
-	/* a constructor. The constructor for a given device is defined in the device source file. 
-	 * When is this called? Not for the static tree. When the scan bus code finds a new device, it must
-	 * create it and insert it into the device tree. To do this, it calls a device constructor. 
-	 * The set of all device constructors is concatenated into the constructors array of structures via the usual 
-	 * gcc hack of naming a segment.  
-	 * The dev_constructor code in device.c iterates over the constructors array. 
-	 * A match consists of a path type, a vendor (which may be ignored if the constructo vendor value is 0), 
-	 * and a device id. 
-	 * When it finds a match, the dev_constructor calls the 
-	 * function constructors->constructor(constructors->constructor) and a new device is created. 
+	/* A constructor. The constructor for a given device is defined in the
+	 * device source file.  When is this called? Not for the static tree.
+	 * When the scan bus code finds a new device, it must create it and
+	 * insert it into the device tree. To initialize it, it calls a device
+	 * constructor.  The set of all device constructors is concatenated
+	 * into the constructors array of structures.
+	 *
+	 * The dev_constructor code in device.c iterates over the constructors
+	 * array.  A match consists of a path type, a vendor (which may be
+	 * ignored if the constructor vendor value is 0), and a device id.
+	 * When it finds a match, the dev_constructor calls the function
+	 * constructors->constructor(constructors->constructor) and a new
+	 * device is created. 
 	 */
-	struct device *(*constructor)(struct constructor *);
+	void (*constructor)(struct device *, struct constructor *);
 
 	/* set device ops */
 	void (*phase1_set_device_operations)(struct device *dev);
@@ -245,7 +248,7 @@
 struct device * dev_find_class (unsigned int class, struct device * from);
 struct device * dev_find_slot (unsigned int bus, unsigned int devfn);
 struct device * dev_find_slot_on_smbus (unsigned int bus, unsigned int addr);
-struct device *default_device_constructor(struct constructor *constructor);
+void default_device_constructor(struct device *dev, struct constructor *constructor);
 
 
 /* Rounding for boundaries. 

Modified: LinuxBIOSv3/include/elf.h
===================================================================
--- LinuxBIOSv3/include/elf.h	2007-06-29 15:32:19 UTC (rev 417)
+++ LinuxBIOSv3/include/elf.h	2007-06-29 16:57:23 UTC (rev 418)
@@ -31,7 +31,7 @@
 #define ELF_H
 
 #include <types.h>
-#include <archelf.h>
+#include <arch/elf.h>
 
 /* Standard ELF types.  */
 

Deleted: LinuxBIOSv3/include/stdlib.h
===================================================================
--- LinuxBIOSv3/include/stdlib.h	2007-06-29 15:32:19 UTC (rev 417)
+++ LinuxBIOSv3/include/stdlib.h	2007-06-29 16:57:23 UTC (rev 418)
@@ -1,22 +0,0 @@
-/*
- * This file is part of the LinuxBIOS project.
- *
- * Copyright (C) 2007 coresystems GmbH
- * (Written by Stefan Reinauer <stepan at coresystems.de> for coresystems GmbH)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
- */
-
-void *malloc(size_t size);
-

Modified: LinuxBIOSv3/lib/console.c
===================================================================
--- LinuxBIOSv3/lib/console.c	2007-06-29 15:32:19 UTC (rev 417)
+++ LinuxBIOSv3/lib/console.c	2007-06-29 16:57:23 UTC (rev 418)
@@ -2,7 +2,6 @@
 #include <hlt.h>
 #include <console.h>
 #include <uart8250.h>
-// FIXME: we need this for varargs
 #include <stdarg.h>
 
 int vtxprintf(void (*)(unsigned char, void *arg), 

Deleted: LinuxBIOSv3/lib/malloc.c
===================================================================
--- LinuxBIOSv3/lib/malloc.c	2007-06-29 15:32:19 UTC (rev 417)
+++ LinuxBIOSv3/lib/malloc.c	2007-06-29 16:57:23 UTC (rev 418)
@@ -1,92 +0,0 @@
-/*
- * This file is part of the LinuxBIOS project.
- *
- * Copyright (C) 2007 Ronald G. Minnich <rminnich at gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
- */
-
-/*
- * Simple non-freeing malloc. There have been about a million versions of
- * this but we need one with a known author. Almost every OS and bootloader
- * has had this at some time or other. 
- */
-
-#include <types.h>
-#include <stdlib.h>
-#include <console.h>
-
-#if 0
-#define MALLOCDBG(x...)
-#else
-#define MALLOCDBG(x...) printk(BIOS_SPEW, x)
-#endif
-
-/*
- * Instead of ldscript magic, just declare an array. The array will consume
- * no bytes in the image, and it won't run into trouble the way the v2
- * allocator could. We do not provide zero'd memory. 
- *
- * Note that the execute-in-place (XIP) code in top of flash is not allowed
- * to call malloc(), since we can't link this in to it. The flash-based code
- * should always be dead simple (in fact, it's not clear we need malloc() at
- * all any more -- we're doing our best to remove all usage of it -- the
- * only real users were elfboot and lzma, and we have removed its usage in
- * elfboot, and will try to remove its usage in lzma). 
- */
-
-#define HEAPSIZE (256 * 1024)
-static unsigned char heap[HEAPSIZE];
-static unsigned char *free_mem_ptr = heap;
-static unsigned long freebytes = HEAPSIZE;
-
-/**
- * Allocate 'size' bytes of memory. The memory is not zero'd.
- * If not enough memory is available, just die.
- *
- * @param size The number of bytes to allocate.
- * @return A pointer to the allocated memory.
- */
-void *malloc(size_t size)
-{
-	void *p;
-
-	MALLOCDBG("%s Enter, size %d, free_mem_ptr %p\n",
-		  __FUNCTION__, size, free_mem_ptr);
-
-	if (size > freebytes) {
-		die("Out of memory.\n");
-	}
-
-	size = (size + 3) & (~3);	/* Align */
-
-	p = free_mem_ptr;
-	free_mem_ptr += size;
-	freebytes -= size;
-
-	MALLOCDBG("malloc 0x%08lx\n", (unsigned long)p);
-
-	return p;
-}
-
-/**
- * Free the specified memory area.
- * This is a no-op, we don't care about freeing memory.
- *
- * @param where A pointer to the memory area to free.
- */
-void free(void *where)
-{
-	/* Don't care. */
-}

Modified: LinuxBIOSv3/util/dtc/dtc-parser.y
===================================================================
--- LinuxBIOSv3/util/dtc/dtc-parser.y	2007-06-29 15:32:19 UTC (rev 417)
+++ LinuxBIOSv3/util/dtc/dtc-parser.y	2007-06-29 16:57:23 UTC (rev 418)
@@ -142,7 +142,7 @@
 		}
 		')' ';' { 
 				/* convention: first property is labeled with path */
-				$6->label = strdup($3.val);
+				$6->label = strdup((char *)$3.val);
 				$$ = $6
 			}
 	|





More information about the coreboot mailing list