arch/s390/kernel/diag/diag310.c

Source file repositories/reference/linux-study-clean/arch/s390/kernel/diag/diag310.c

File Facts

System
Linux kernel
Corpus path
arch/s390/kernel/diag/diag310.c
Extension
.c
Size
5923 bytes
Lines
277
Domain
Architecture Layer
Bucket
arch/s390
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/*
 * Request memory topology information via diag0x310.
 *
 * Copyright IBM Corp. 2025
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#include <asm/diag.h>
#include <asm/sclp.h>
#include <uapi/asm/diag.h>
#include "diag_ioctl.h"

#define DIAG310_LEVELMIN 1
#define DIAG310_LEVELMAX 6

enum diag310_sc {
	DIAG310_SUBC_0 = 0,
	DIAG310_SUBC_1 = 1,
	DIAG310_SUBC_4 = 4,
	DIAG310_SUBC_5 = 5
};

enum diag310_retcode {
	DIAG310_RET_SUCCESS	= 0x0001,
	DIAG310_RET_BUSY	= 0x0101,
	DIAG310_RET_OPNOTSUPP	= 0x0102,
	DIAG310_RET_SC4_INVAL	= 0x0401,
	DIAG310_RET_SC4_NODATA	= 0x0402,
	DIAG310_RET_SC5_INVAL	= 0x0501,
	DIAG310_RET_SC5_NODATA	= 0x0502,
	DIAG310_RET_SC5_ESIZE	= 0x0503
};

union diag310_response {
	u64 response;
	struct {
		u64 result	: 32;
		u64		: 16;
		u64 rc		: 16;
	};
};

union diag310_req_subcode {
	u64 subcode;
	struct {
		u64		: 48;
		u64 st		: 8;
		u64 sc		: 8;
	};
};

union diag310_req_size {
	u64 size;
	struct {
		u64 page_count	: 32;
		u64		: 32;
	};
};

static inline unsigned long diag310(unsigned long subcode, unsigned long size, void *addr)
{
	union register_pair rp = { .even = (unsigned long)addr, .odd = size };

	diag_stat_inc(DIAG_STAT_X310);
	asm volatile("diag	%[rp],%[subcode],0x310"
		     : [rp] "+d" (rp.pair)
		     : [subcode] "d" (subcode)
		     : "memory");
	return rp.odd;
}

static int diag310_result_to_errno(unsigned int result)
{
	switch (result) {
	case DIAG310_RET_BUSY:
		return -EBUSY;
	case DIAG310_RET_OPNOTSUPP:
		return -EOPNOTSUPP;
	default:
		return -EINVAL;
	}
}

static int diag310_get_subcode_mask(unsigned long *mask)
{
	union diag310_response res;

Annotation

Implementation Notes