Commit 93fb82b5 authored by Vikram Narayanan's avatar Vikram Narayanan
Browse files

foobar: Add foobar toy subsystem

Add a toy subsystem as an example for static analysis. Also add a dummy
device driver for foobar.
parent 1b9eb83f
......@@ -562,6 +562,7 @@ scripts: scripts_basic include/config/auto.conf include/config/tristate.conf \
init-y := init/
drivers-y := drivers/ sound/ firmware/
net-y := net/
foobar-y := foobar/
libs-y := lib/
core-y := usr/
virt-y := virt/
......@@ -899,7 +900,7 @@ core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
$(core-y) $(core-m) $(drivers-y) $(drivers-m) \
$(net-y) $(net-m) $(libs-y) $(libs-m) $(virt-y)))
$(net-y) $(net-m) $(libs-y) $(libs-m) $(virt-y) $(foobar-y)))
vmlinux-alldirs := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \
$(init-) $(core-) $(drivers-) $(net-) $(libs-) $(virt-))))
......@@ -908,6 +909,7 @@ init-y := $(patsubst %/, %/built-in.o, $(init-y))
core-y := $(patsubst %/, %/built-in.o, $(core-y))
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
net-y := $(patsubst %/, %/built-in.o, $(net-y))
foobar-y := $(patsubst %/, %/built-in.o, $(foobar-y))
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y := $(libs-y1) $(libs-y2)
......@@ -915,7 +917,7 @@ virt-y := $(patsubst %/, %/built-in.o, $(virt-y))
# Externally visible symbols (used by link-vmlinux.sh)
export KBUILD_VMLINUX_INIT := $(head-y) $(init-y)
export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y) $(drivers-y) $(net-y) $(virt-y)
export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y) $(drivers-y) $(net-y) $(virt-y) $(foobar-y)
export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds
export LDFLAGS_vmlinux
# used by scripts/pacmage/Makefile
......
......@@ -2776,3 +2776,5 @@ source "crypto/Kconfig"
source "arch/x86/kvm/Kconfig"
source "lib/Kconfig"
source "foobar/Kconfig"
......@@ -202,4 +202,5 @@ source "drivers/hwtracing/intel_th/Kconfig"
source "drivers/fpga/Kconfig"
source "drivers/foobar/Kconfig"
endmenu
......@@ -173,3 +173,4 @@ obj-$(CONFIG_STM) += hwtracing/stm/
obj-$(CONFIG_ANDROID) += android/
obj-$(CONFIG_NVMEM) += nvmem/
obj-$(CONFIG_FPGA) += fpga/
obj-$(CONFIG_FOOBAR) += foobar/
menuconfig FOOBARDEVICES
depends on FOOBAR
bool "Foobar device support"
---help---
Foobar device driver support
If unsure, say Y.
if FOOBARDEVICES
config FOOBAR_DUMMY
tristate "Dummy foobar driver support"
---help---
Foobar dummy device driver.
To compile this driver as a module, choose M here: the module
will be called dummy.
endif # FOOBARDEVICES
obj-$(CONFIG_FOOBAR_DUMMY) += dummy.o
/* dummy.c: a dummy foobar driver */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/foobar_device.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#define DRV_NAME "foobardummy"
#define DRV_VERSION "1.0"
static int dummy_dev_init(struct foobar_device *dev)
{
dev->dstats = kmalloc(sizeof(struct foo_stats), GFP_KERNEL);
if (!dev->dstats)
return -ENOMEM;
return 0;
}
static void dummy_dev_uninit(struct foobar_device *dev)
{
kfree(dev->dstats);
}
static const struct foobar_device_ops dummy_foobardev_ops = {
.init = dummy_dev_init,
.uninit = dummy_dev_uninit,
};
int numdummies = 0;
/* Number of dummy devices to be set up by this module. */
module_param(numdummies, int, 0);
MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
struct foobar_device *dev_dummy;
static int __init dummy_init_module(void)
{
int err;
dev_dummy = alloc_foobardev(0, "dummy0");
if (!dev_dummy)
return -ENOMEM;
dev_dummy->foobardev_ops = &dummy_foobardev_ops;
err = register_foobar(dev_dummy);
if (err < 0)
goto err;
return 0;
err:
free_foobardev(dev_dummy);
return err;
}
static void __exit dummy_cleanup_module(void)
{
unregister_foobar(dev_dummy);
}
module_init(dummy_init_module);
module_exit(dummy_cleanup_module);
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
#
# Foobar config
#
menuconfig FOOBAR
bool "Foobar support"
---help---
Toy subsystem for working with kernel static analysis
#
# Makefile for the linux foobar
#
obj-$(CONFIG_FOOBAR) := dev.o
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/foobar_device.h>
#include <linux/slab.h>
#include <linux/err.h>
int register_foobar(struct foobar_device *dev)
{
int ret;
dev->hw_features |= FOOBAR_IRQ_DELAY;
dev->features |= FOOBAR_SOFTIRQ_ENABLE;
dev->wanted_features = dev->features & dev->hw_features;
if (!(dev->flags & FOO_LOOPBACK))
dev->hw_features |= FOOBAR_ZERO_COPY;
/* Init, if this function is available */
if (dev->foobardev_ops->init) {
ret = dev->foobardev_ops->init(dev);
if (ret) {
if (ret > 0)
ret = -EIO;
goto out;
}
}
printk("%s, foobar registered\n", __func__);
out:
return ret;
}
EXPORT_SYMBOL(register_foobar);
void unregister_foobar(struct foobar_device *dev)
{
/* uninit, if this function is available */
if (dev->foobardev_ops->uninit) {
dev->foobardev_ops->uninit(dev);
}
printk("%s, foobar unregistered\n", __func__);
}
EXPORT_SYMBOL(unregister_foobar);
struct foobar_device *alloc_foobardev(int id, const char* name)
{
struct foobar_device *dev = kmalloc(sizeof(struct foobar_device), GFP_KERNEL);
strncpy(dev->name, name, sizeof(dev->name));
dev->id = id;
return dev;
}
EXPORT_SYMBOL(alloc_foobardev);
void free_foobardev(struct foobar_device *dev)
{
kfree(dev);
}
EXPORT_SYMBOL(free_foobardev);
#ifndef _FOOBAR_DEVICE_H
#define _FOOBAR_DEVICE_H
typedef u64 foobar_features_t;
/* features */
#define FOOBAR_IRQ_DELAY (1 << 10)
#define FOOBAR_SOFTIRQ_ENABLE (1 << 11)
#define FOOBAR_ZERO_COPY (1 << 12)
/* flags */
#define FOO_LOOPBACK 4
struct foobar_device;
struct foobar_device_ops {
int (*init)(struct foobar_device *dev);
void (*uninit)(struct foobar_device *dev);
};
struct foo_stats {
unsigned num_tx_packets;
unsigned num_rx_packets;
};
struct foobar_device {
char name[32];
unsigned long id;
unsigned long mem_end;
unsigned long mem_start;
unsigned long base_addr;
int irq;
unsigned long state;
unsigned int flags;
unsigned int priv_flags;
struct foo_stats *dstats;
foobar_features_t features;
foobar_features_t hw_features;
foobar_features_t wanted_features;
const struct foobar_device_ops *foobardev_ops;
};
int register_foobar(struct foobar_device *dev);
void unregister_foobar(struct foobar_device *dev);
struct foobar_device *alloc_foobardev(int id, const char* name);
void free_foobardev(struct foobar_device *dev);
#endif /* _FOOBAR_DEVICE_H */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment