Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba0234ec authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6

* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6: (24 commits)
  [S390] drivers/s390/char: Use kmemdup
  [S390] drivers/s390/char: Use kstrdup
  [S390] debug: enable exception-trace debug facility
  [S390] s390_hypfs: Add new attributes
  [S390] qdio: remove API wrappers
  [S390] qdio: set correct bit in dsci
  [S390] qdio: dont convert timestamps to microseconds
  [S390] qdio: remove memset hack
  [S390] qdio: prevent starvation on PCI devices
  [S390] qdio: count number of qdio interrupts
  [S390] user space fault: report fault before calling do_exit
  [S390] topology: expose core identifier
  [S390] dasd: remove uid from devmap
  [S390] dasd: add dynamic pav toleration
  [S390] vdso: add missing vdso_install target
  [S390] vdso: remove redundant check for CONFIG_64BIT
  [S390] avoid default_llseek in s390 drivers
  [S390] vmcp: disallow modular build
  [S390] add breaking event address for user space
  [S390] virtualization aware cpu measurement
  ...
parents 537b60d1 939e379e
Loading
Loading
Loading
Loading
+0 −7
Original line number Diff line number Diff line
@@ -444,13 +444,6 @@ config FORCE_MAX_ZONEORDER
	int
	default "9"

config PROCESS_DEBUG
	bool "Show crashed user process info"
	help
	  Say Y to print all process fault locations to the console.  This is
	  a debugging option; you probably do not want to set it unless you
	  are an S390 port maintainer.

config PFAULT
	bool "Pseudo page fault support"
	help
+6 −0
Original line number Diff line number Diff line
@@ -116,6 +116,12 @@ image bzImage: vmlinux
zfcpdump:
	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@

vdso_install:
ifeq ($(CONFIG_64BIT),y)
	$(Q)$(MAKE) $(build)=arch/$(ARCH)/kernel/vdso64 $@
endif
	$(Q)$(MAKE) $(build)=arch/$(ARCH)/kernel/vdso32 $@

archclean:
	$(Q)$(MAKE) $(clean)=$(boot)

+4 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@

#include <linux/fs.h>
#include <linux/types.h>
#include <linux/debugfs.h>

#define REG_FILE_MODE    0440
#define UPDATE_FILE_MODE 0220
@@ -34,6 +35,9 @@ extern int hypfs_diag_create_files(struct super_block *sb, struct dentry *root);

/* VM Hypervisor */
extern int hypfs_vm_init(void);
extern void hypfs_vm_exit(void);
extern int hypfs_vm_create_files(struct super_block *sb, struct dentry *root);

/* Directory for debugfs files */
extern struct dentry *hypfs_dbfs_dir;
#endif /* _HYPFS_H_ */
+116 −7
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <asm/ebcdic.h>
#include "hypfs.h"

@@ -22,6 +23,8 @@
#define CPU_NAME_LEN 16		/* type name len of cpus in diag224 name table */
#define TMP_SIZE 64		/* size of temporary buffers */

#define DBFS_D204_HDR_VERSION	0

/* diag 204 subcodes */
enum diag204_sc {
	SUBC_STIB4 = 4,
@@ -47,6 +50,8 @@ static void *diag204_buf; /* 4K aligned buffer for diag204 data */
static void *diag204_buf_vmalloc;	/* vmalloc pointer for diag204 data */
static int diag204_buf_pages;		/* number of pages for diag204 data */

static struct dentry *dbfs_d204_file;

/*
 * DIAG 204 data structures and member access functions.
 *
@@ -364,18 +369,21 @@ static void diag204_free_buffer(void)
	} else {
		free_pages((unsigned long) diag204_buf, 0);
	}
	diag204_buf_pages = 0;
	diag204_buf = NULL;
}

static void *page_align_ptr(void *ptr)
{
	return (void *) PAGE_ALIGN((unsigned long) ptr);
}

static void *diag204_alloc_vbuf(int pages)
{
	/* The buffer has to be page aligned! */
	diag204_buf_vmalloc = vmalloc(PAGE_SIZE * (pages + 1));
	if (!diag204_buf_vmalloc)
		return ERR_PTR(-ENOMEM);
	diag204_buf = (void*)((unsigned long)diag204_buf_vmalloc
				& ~0xfffUL) + 0x1000;
	diag204_buf = page_align_ptr(diag204_buf_vmalloc);
	diag204_buf_pages = pages;
	return diag204_buf;
}
@@ -468,17 +476,26 @@ static int diag204_probe(void)
	return rc;
}

static int diag204_do_store(void *buf, int pages)
{
	int rc;

	rc = diag204((unsigned long) diag204_store_sc |
		     (unsigned long) diag204_info_type, pages, buf);
	return rc < 0 ? -ENOSYS : 0;
}

static void *diag204_store(void)
{
	void *buf;
	int pages;
	int pages, rc;

	buf = diag204_get_buffer(diag204_info_type, &pages);
	if (IS_ERR(buf))
		goto out;
	if (diag204((unsigned long)diag204_store_sc |
		    (unsigned long)diag204_info_type, pages, buf) < 0)
		return ERR_PTR(-ENOSYS);
	rc = diag204_do_store(buf, pages);
	if (rc)
		return ERR_PTR(rc);
out:
	return buf;
}
@@ -526,6 +543,92 @@ static int diag224_idx2name(int index, char *name)
	return 0;
}

struct dbfs_d204_hdr {
	u64	len;		/* Length of d204 buffer without header */
	u16	version;	/* Version of header */
	u8	sc;		/* Used subcode */
	char	reserved[53];
} __attribute__ ((packed));

struct dbfs_d204 {
	struct dbfs_d204_hdr	hdr;	/* 64 byte header */
	char			buf[];	/* d204 buffer */
} __attribute__ ((packed));

struct dbfs_d204_private {
	struct dbfs_d204	*d204;	/* Aligned d204 data with header */
	void			*base;	/* Base pointer (needed for vfree) */
};

static int dbfs_d204_open(struct inode *inode, struct file *file)
{
	struct dbfs_d204_private *data;
	struct dbfs_d204 *d204;
	int rc, buf_size;

	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;
	buf_size = PAGE_SIZE * (diag204_buf_pages + 1) + sizeof(d204->hdr);
	data->base = vmalloc(buf_size);
	if (!data->base) {
		rc = -ENOMEM;
		goto fail_kfree_data;
	}
	memset(data->base, 0, buf_size);
	d204 = page_align_ptr(data->base + sizeof(d204->hdr))
		- sizeof(d204->hdr);
	rc = diag204_do_store(&d204->buf, diag204_buf_pages);
	if (rc)
		goto fail_vfree_base;
	d204->hdr.version = DBFS_D204_HDR_VERSION;
	d204->hdr.len = PAGE_SIZE * diag204_buf_pages;
	d204->hdr.sc = diag204_store_sc;
	data->d204 = d204;
	file->private_data = data;
	return nonseekable_open(inode, file);

fail_vfree_base:
	vfree(data->base);
fail_kfree_data:
	kfree(data);
	return rc;
}

static int dbfs_d204_release(struct inode *inode, struct file *file)
{
	struct dbfs_d204_private *data = file->private_data;

	vfree(data->base);
	kfree(data);
	return 0;
}

static ssize_t dbfs_d204_read(struct file *file, char __user *buf,
			      size_t size, loff_t *ppos)
{
	struct dbfs_d204_private *data = file->private_data;

	return simple_read_from_buffer(buf, size, ppos, data->d204,
				       data->d204->hdr.len +
				       sizeof(data->d204->hdr));
}

static const struct file_operations dbfs_d204_ops = {
	.open		= dbfs_d204_open,
	.read		= dbfs_d204_read,
	.release	= dbfs_d204_release,
};

static int hypfs_dbfs_init(void)
{
	dbfs_d204_file = debugfs_create_file("diag_204", 0400, hypfs_dbfs_dir,
					     NULL, &dbfs_d204_ops);
	if (IS_ERR(dbfs_d204_file))
		return PTR_ERR(dbfs_d204_file);
	return 0;
}

__init int hypfs_diag_init(void)
{
	int rc;
@@ -540,11 +643,17 @@ __init int hypfs_diag_init(void)
		pr_err("The hardware system does not provide all "
		       "functions required by hypfs\n");
	}
	if (diag204_info_type == INFO_EXT) {
		rc = hypfs_dbfs_init();
		if (rc)
			diag204_free_buffer();
	}
	return rc;
}

void hypfs_diag_exit(void)
{
	debugfs_remove(dbfs_d204_file);
	diag224_delete_name_table();
	diag204_free_buffer();
}
+80 −7
Original line number Diff line number Diff line
@@ -10,14 +10,18 @@
#include <linux/string.h>
#include <linux/vmalloc.h>
#include <asm/ebcdic.h>
#include <asm/timex.h>
#include "hypfs.h"

#define NAME_LEN 8
#define DBFS_D2FC_HDR_VERSION 0

static char local_guest[] = "        ";
static char all_guests[] = "*       ";
static char *guest_query;

static struct dentry *dbfs_d2fc_file;

struct diag2fc_data {
	__u32 version;
	__u32 flags;
@@ -76,23 +80,26 @@ static int diag2fc(int size, char* query, void *addr)
		return -residual_cnt;
}

static struct diag2fc_data *diag2fc_store(char *query, int *count)
/*
 * Allocate buffer for "query" and store diag 2fc at "offset"
 */
static void *diag2fc_store(char *query, unsigned int *count, int offset)
{
	void *data;
	int size;
	struct diag2fc_data *data;

	do {
		size = diag2fc(0, query, NULL);
		if (size < 0)
			return ERR_PTR(-EACCES);
		data = vmalloc(size);
		data = vmalloc(size + offset);
		if (!data)
			return ERR_PTR(-ENOMEM);
		if (diag2fc(size, query, data) == 0)
		if (diag2fc(size, query, data + offset) == 0)
			break;
		vfree(data);
	} while (1);
	*count = (size / sizeof(*data));
	*count = (size / sizeof(struct diag2fc_data));

	return data;
}
@@ -168,9 +175,10 @@ int hypfs_vm_create_files(struct super_block *sb, struct dentry *root)
{
	struct dentry *dir, *file;
	struct diag2fc_data *data;
	int rc, i, count = 0;
	unsigned int count = 0;
	int rc, i;

	data = diag2fc_store(guest_query, &count);
	data = diag2fc_store(guest_query, &count, 0);
	if (IS_ERR(data))
		return PTR_ERR(data);

@@ -218,8 +226,61 @@ int hypfs_vm_create_files(struct super_block *sb, struct dentry *root)
	return rc;
}

struct dbfs_d2fc_hdr {
	u64	len;		/* Length of d2fc buffer without header */
	u16	version;	/* Version of header */
	char	tod_ext[16];	/* TOD clock for d2fc */
	u64	count;		/* Number of VM guests in d2fc buffer */
	char	reserved[30];
} __attribute__ ((packed));

struct dbfs_d2fc {
	struct dbfs_d2fc_hdr	hdr;	/* 64 byte header */
	char			buf[];	/* d2fc buffer */
} __attribute__ ((packed));

static int dbfs_d2fc_open(struct inode *inode, struct file *file)
{
	struct dbfs_d2fc *data;
	unsigned int count;

	data = diag2fc_store(guest_query, &count, sizeof(data->hdr));
	if (IS_ERR(data))
		return PTR_ERR(data);
	get_clock_ext(data->hdr.tod_ext);
	data->hdr.len = count * sizeof(struct diag2fc_data);
	data->hdr.version = DBFS_D2FC_HDR_VERSION;
	data->hdr.count = count;
	memset(&data->hdr.reserved, 0, sizeof(data->hdr.reserved));
	file->private_data = data;
	return nonseekable_open(inode, file);
}

static int dbfs_d2fc_release(struct inode *inode, struct file *file)
{
	diag2fc_free(file->private_data);
	return 0;
}

static ssize_t dbfs_d2fc_read(struct file *file, char __user *buf,
				    size_t size, loff_t *ppos)
{
	struct dbfs_d2fc *data = file->private_data;

	return simple_read_from_buffer(buf, size, ppos, data, data->hdr.len +
				       sizeof(struct dbfs_d2fc_hdr));
}

static const struct file_operations dbfs_d2fc_ops = {
	.open		= dbfs_d2fc_open,
	.read		= dbfs_d2fc_read,
	.release	= dbfs_d2fc_release,
};

int hypfs_vm_init(void)
{
	if (!MACHINE_IS_VM)
		return 0;
	if (diag2fc(0, all_guests, NULL) > 0)
		guest_query = all_guests;
	else if (diag2fc(0, local_guest, NULL) > 0)
@@ -227,5 +288,17 @@ int hypfs_vm_init(void)
	else
		return -EACCES;

	dbfs_d2fc_file = debugfs_create_file("diag_2fc", 0400, hypfs_dbfs_dir,
					     NULL, &dbfs_d2fc_ops);
	if (IS_ERR(dbfs_d2fc_file))
		return PTR_ERR(dbfs_d2fc_file);

	return 0;
}

void hypfs_vm_exit(void)
{
	if (!MACHINE_IS_VM)
		return;
	debugfs_remove(dbfs_d2fc_file);
}
Loading