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

Commit 444f0e54 authored by Gerald Schaefer's avatar Gerald Schaefer Committed by Martin Schwidefsky
Browse files

[S390] Show loaded DCSS segments under /proc/iomem.



Currently loaded DCSS segments are now listed in /proc/iomem with
their name followed by a trailing "(DCSS)".

Signed-off-by: default avatarGerald Schaefer <geraldsc@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 18374d37
Loading
Loading
Loading
Loading
+54 −10
Original line number Original line Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/module.h>
#include <linux/bootmem.h>
#include <linux/bootmem.h>
#include <linux/ctype.h>
#include <linux/ctype.h>
#include <linux/ioport.h>
#include <asm/page.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/pgtable.h>
#include <asm/ebcdic.h>
#include <asm/ebcdic.h>
@@ -70,6 +71,7 @@ struct qin64 {
struct dcss_segment {
struct dcss_segment {
	struct list_head list;
	struct list_head list;
	char dcss_name[8];
	char dcss_name[8];
	char res_name[15];
	unsigned long start_addr;
	unsigned long start_addr;
	unsigned long end;
	unsigned long end;
	atomic_t ref_count;
	atomic_t ref_count;
@@ -77,6 +79,7 @@ struct dcss_segment {
	unsigned int vm_segtype;
	unsigned int vm_segtype;
	struct qrange range[6];
	struct qrange range[6];
	int segcnt;
	int segcnt;
	struct resource *res;
};
};


static DEFINE_MUTEX(dcss_lock);
static DEFINE_MUTEX(dcss_lock);
@@ -303,6 +306,29 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
		goto out_free;
		goto out_free;
	}
	}


	seg->res = kzalloc(sizeof(struct resource), GFP_KERNEL);
	if (seg->res == NULL) {
		rc = -ENOMEM;
		goto out_shared;
	}
	seg->res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
	seg->res->start = seg->start_addr;
	seg->res->end = seg->end;
	memcpy(&seg->res_name, seg->dcss_name, 8);
	EBCASC(seg->res_name, 8);
	seg->res_name[8] = '\0';
	strncat(seg->res_name, " (DCSS)", 7);
	seg->res->name = seg->res_name;
	rc = seg->vm_segtype;
	if (rc == SEG_TYPE_SC ||
	    ((rc == SEG_TYPE_SR || rc == SEG_TYPE_ER) && !do_nonshared))
		seg->res->flags |= IORESOURCE_READONLY;
	if (request_resource(&iomem_resource, seg->res)) {
		rc = -EBUSY;
		kfree(seg->res);
		goto out_shared;
	}

	if (do_nonshared)
	if (do_nonshared)
		dcss_command = DCSS_LOADNSR;
		dcss_command = DCSS_LOADNSR;
	else
	else
@@ -316,12 +342,11 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
		rc = dcss_diag_translate_rc (seg->end);
		rc = dcss_diag_translate_rc (seg->end);
		dcss_diag(DCSS_PURGESEG, seg->dcss_name,
		dcss_diag(DCSS_PURGESEG, seg->dcss_name,
				&seg->start_addr, &seg->end);
				&seg->start_addr, &seg->end);
		goto out_shared;
		goto out_resource;
	}
	}
	seg->do_nonshared = do_nonshared;
	seg->do_nonshared = do_nonshared;
	atomic_set(&seg->ref_count, 1);
	atomic_set(&seg->ref_count, 1);
	list_add(&seg->list, &dcss_list);
	list_add(&seg->list, &dcss_list);
	rc = seg->vm_segtype;
	*addr = seg->start_addr;
	*addr = seg->start_addr;
	*end  = seg->end;
	*end  = seg->end;
	if (do_nonshared)
	if (do_nonshared)
@@ -329,12 +354,16 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
				"type %s in non-shared mode\n", name,
				"type %s in non-shared mode\n", name,
				(void*)seg->start_addr, (void*)seg->end,
				(void*)seg->start_addr, (void*)seg->end,
				segtype_string[seg->vm_segtype]);
				segtype_string[seg->vm_segtype]);
	else
	else {
		PRINT_INFO ("segment_load: loaded segment %s range %p .. %p "
		PRINT_INFO ("segment_load: loaded segment %s range %p .. %p "
				"type %s in shared mode\n", name,
				"type %s in shared mode\n", name,
				(void*)seg->start_addr, (void*)seg->end,
				(void*)seg->start_addr, (void*)seg->end,
				segtype_string[seg->vm_segtype]);
				segtype_string[seg->vm_segtype]);
	}
	goto out;
	goto out;
 out_resource:
	release_resource(seg->res);
	kfree(seg->res);
 out_shared:
 out_shared:
	remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
	remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
 out_free:
 out_free:
@@ -401,6 +430,7 @@ segment_load (char *name, int do_nonshared, unsigned long *addr,
 * -ENOENT  : no such segment (segment gone!)
 * -ENOENT  : no such segment (segment gone!)
 * -EAGAIN  : segment is in use by other exploiters, try later
 * -EAGAIN  : segment is in use by other exploiters, try later
 * -EINVAL  : no segment with the given name is currently loaded - name invalid
 * -EINVAL  : no segment with the given name is currently loaded - name invalid
 * -EBUSY   : segment can temporarily not be used (overlaps with dcss)
 * 0	    : operation succeeded
 * 0	    : operation succeeded
 */
 */
int
int
@@ -428,12 +458,24 @@ segment_modify_shared (char *name, int do_nonshared)
		rc = -EAGAIN;
		rc = -EAGAIN;
		goto out_unlock;
		goto out_unlock;
	}
	}
	dcss_diag(DCSS_PURGESEG, seg->dcss_name,
	release_resource(seg->res);
		  &dummy, &dummy);
	if (do_nonshared) {
	if (do_nonshared)
		dcss_command = DCSS_LOADNSR;
		dcss_command = DCSS_LOADNSR;
	else
		seg->res->flags &= ~IORESOURCE_READONLY;
	} else {
		dcss_command = DCSS_LOADNOLY;
		dcss_command = DCSS_LOADNOLY;
		if (seg->vm_segtype == SEG_TYPE_SR ||
		    seg->vm_segtype == SEG_TYPE_ER)
			seg->res->flags |= IORESOURCE_READONLY;
	}
	if (request_resource(&iomem_resource, seg->res)) {
		PRINT_WARN("segment_modify_shared: could not reload segment %s"
			   " - overlapping resources\n", name);
		rc = -EBUSY;
		kfree(seg->res);
		goto out_del;
	}
	dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
	diag_cc = dcss_diag(dcss_command, seg->dcss_name,
	diag_cc = dcss_diag(dcss_command, seg->dcss_name,
			&seg->start_addr, &seg->end);
			&seg->start_addr, &seg->end);
	if (diag_cc > 1) {
	if (diag_cc > 1) {
@@ -446,9 +488,9 @@ segment_modify_shared (char *name, int do_nonshared)
	rc = 0;
	rc = 0;
	goto out_unlock;
	goto out_unlock;
 out_del:
 out_del:
	remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
	list_del(&seg->list);
	list_del(&seg->list);
	dcss_diag(DCSS_PURGESEG, seg->dcss_name,
	dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
		  &dummy, &dummy);
	kfree(seg);
	kfree(seg);
 out_unlock:
 out_unlock:
	mutex_unlock(&dcss_lock);
	mutex_unlock(&dcss_lock);
@@ -478,6 +520,8 @@ segment_unload(char *name)
	}
	}
	if (atomic_dec_return(&seg->ref_count) != 0)
	if (atomic_dec_return(&seg->ref_count) != 0)
		goto out_unlock;
		goto out_unlock;
	release_resource(seg->res);
	kfree(seg->res);
	remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
	remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
	list_del(&seg->list);
	list_del(&seg->list);
	dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
	dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
+2 −2
Original line number Original line Diff line number Diff line
@@ -230,7 +230,7 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch
					   SEGMENT_SHARED);
					   SEGMENT_SHARED);
		if (rc < 0) {
		if (rc < 0) {
			BUG_ON(rc == -EINVAL);
			BUG_ON(rc == -EINVAL);
			if (rc == -EIO || rc == -ENOENT)
			if (rc != -EAGAIN)
				goto removeseg;
				goto removeseg;
		} else {
		} else {
			dev_info->is_shared = 1;
			dev_info->is_shared = 1;
@@ -253,7 +253,7 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch
					   SEGMENT_EXCLUSIVE);
					   SEGMENT_EXCLUSIVE);
		if (rc < 0) {
		if (rc < 0) {
			BUG_ON(rc == -EINVAL);
			BUG_ON(rc == -EINVAL);
			if (rc == -EIO || rc == -ENOENT)
			if (rc != -EAGAIN)
				goto removeseg;
				goto removeseg;
		} else {
		} else {
			dev_info->is_shared = 0;
			dev_info->is_shared = 0;