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@coresystems.de Acked-by: Ronald G. Minnich rminnich@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@gmail.com * Copyright (C) 2004-2005 Li-Ta Lo ollie@lanl.gov * Copyright (C) 2005-2006 Tyan - * (Written by Yinghai Lu yhlu@tyan.com for Tyan) + * (Written by Yinghai Lu for Tyan) * Copyright (C) 2005-2006 Stefan Reinauer stepan@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@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@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 } |