cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

acpi_dbg.c (18217B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * ACPI AML interfacing support
      4 *
      5 * Copyright (C) 2015, Intel Corporation
      6 * Authors: Lv Zheng <lv.zheng@intel.com>
      7 */
      8
      9/* #define DEBUG */
     10#define pr_fmt(fmt) "ACPI: AML: " fmt
     11
     12#include <linux/kernel.h>
     13#include <linux/module.h>
     14#include <linux/wait.h>
     15#include <linux/poll.h>
     16#include <linux/sched.h>
     17#include <linux/kthread.h>
     18#include <linux/proc_fs.h>
     19#include <linux/debugfs.h>
     20#include <linux/circ_buf.h>
     21#include <linux/acpi.h>
     22#include "internal.h"
     23
     24#define ACPI_AML_BUF_ALIGN	(sizeof (acpi_size))
     25#define ACPI_AML_BUF_SIZE	PAGE_SIZE
     26
     27#define circ_count(circ) \
     28	(CIRC_CNT((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
     29#define circ_count_to_end(circ) \
     30	(CIRC_CNT_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
     31#define circ_space(circ) \
     32	(CIRC_SPACE((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
     33#define circ_space_to_end(circ) \
     34	(CIRC_SPACE_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
     35
     36#define ACPI_AML_OPENED		0x0001
     37#define ACPI_AML_CLOSED		0x0002
     38#define ACPI_AML_IN_USER	0x0004 /* user space is writing cmd */
     39#define ACPI_AML_IN_KERN	0x0008 /* kernel space is reading cmd */
     40#define ACPI_AML_OUT_USER	0x0010 /* user space is reading log */
     41#define ACPI_AML_OUT_KERN	0x0020 /* kernel space is writing log */
     42#define ACPI_AML_USER		(ACPI_AML_IN_USER | ACPI_AML_OUT_USER)
     43#define ACPI_AML_KERN		(ACPI_AML_IN_KERN | ACPI_AML_OUT_KERN)
     44#define ACPI_AML_BUSY		(ACPI_AML_USER | ACPI_AML_KERN)
     45#define ACPI_AML_OPEN		(ACPI_AML_OPENED | ACPI_AML_CLOSED)
     46
     47struct acpi_aml_io {
     48	wait_queue_head_t wait;
     49	unsigned long flags;
     50	unsigned long users;
     51	struct mutex lock;
     52	struct task_struct *thread;
     53	char out_buf[ACPI_AML_BUF_SIZE] __aligned(ACPI_AML_BUF_ALIGN);
     54	struct circ_buf out_crc;
     55	char in_buf[ACPI_AML_BUF_SIZE] __aligned(ACPI_AML_BUF_ALIGN);
     56	struct circ_buf in_crc;
     57	acpi_osd_exec_callback function;
     58	void *context;
     59	unsigned long usages;
     60};
     61
     62static struct acpi_aml_io acpi_aml_io;
     63static bool acpi_aml_initialized;
     64static struct file *acpi_aml_active_reader;
     65static struct dentry *acpi_aml_dentry;
     66
     67static inline bool __acpi_aml_running(void)
     68{
     69	return acpi_aml_io.thread ? true : false;
     70}
     71
     72static inline bool __acpi_aml_access_ok(unsigned long flag)
     73{
     74	/*
     75	 * The debugger interface is in opened state (OPENED && !CLOSED),
     76	 * then it is allowed to access the debugger buffers from either
     77	 * user space or the kernel space.
     78	 * In addition, for the kernel space, only the debugger thread
     79	 * (thread ID matched) is allowed to access.
     80	 */
     81	if (!(acpi_aml_io.flags & ACPI_AML_OPENED) ||
     82	    (acpi_aml_io.flags & ACPI_AML_CLOSED) ||
     83	    !__acpi_aml_running())
     84		return false;
     85	if ((flag & ACPI_AML_KERN) &&
     86	    current != acpi_aml_io.thread)
     87		return false;
     88	return true;
     89}
     90
     91static inline bool __acpi_aml_readable(struct circ_buf *circ, unsigned long flag)
     92{
     93	/*
     94	 * Another read is not in progress and there is data in buffer
     95	 * available for read.
     96	 */
     97	if (!(acpi_aml_io.flags & flag) && circ_count(circ))
     98		return true;
     99	return false;
    100}
    101
    102static inline bool __acpi_aml_writable(struct circ_buf *circ, unsigned long flag)
    103{
    104	/*
    105	 * Another write is not in progress and there is buffer space
    106	 * available for write.
    107	 */
    108	if (!(acpi_aml_io.flags & flag) && circ_space(circ))
    109		return true;
    110	return false;
    111}
    112
    113static inline bool __acpi_aml_busy(void)
    114{
    115	if (acpi_aml_io.flags & ACPI_AML_BUSY)
    116		return true;
    117	return false;
    118}
    119
    120static inline bool __acpi_aml_used(void)
    121{
    122	return acpi_aml_io.usages ? true : false;
    123}
    124
    125static inline bool acpi_aml_running(void)
    126{
    127	bool ret;
    128
    129	mutex_lock(&acpi_aml_io.lock);
    130	ret = __acpi_aml_running();
    131	mutex_unlock(&acpi_aml_io.lock);
    132	return ret;
    133}
    134
    135static bool acpi_aml_busy(void)
    136{
    137	bool ret;
    138
    139	mutex_lock(&acpi_aml_io.lock);
    140	ret = __acpi_aml_busy();
    141	mutex_unlock(&acpi_aml_io.lock);
    142	return ret;
    143}
    144
    145static bool acpi_aml_used(void)
    146{
    147	bool ret;
    148
    149	/*
    150	 * The usage count is prepared to avoid race conditions between the
    151	 * starts and the stops of the debugger thread.
    152	 */
    153	mutex_lock(&acpi_aml_io.lock);
    154	ret = __acpi_aml_used();
    155	mutex_unlock(&acpi_aml_io.lock);
    156	return ret;
    157}
    158
    159static bool acpi_aml_kern_readable(void)
    160{
    161	bool ret;
    162
    163	mutex_lock(&acpi_aml_io.lock);
    164	ret = !__acpi_aml_access_ok(ACPI_AML_IN_KERN) ||
    165	      __acpi_aml_readable(&acpi_aml_io.in_crc, ACPI_AML_IN_KERN);
    166	mutex_unlock(&acpi_aml_io.lock);
    167	return ret;
    168}
    169
    170static bool acpi_aml_kern_writable(void)
    171{
    172	bool ret;
    173
    174	mutex_lock(&acpi_aml_io.lock);
    175	ret = !__acpi_aml_access_ok(ACPI_AML_OUT_KERN) ||
    176	      __acpi_aml_writable(&acpi_aml_io.out_crc, ACPI_AML_OUT_KERN);
    177	mutex_unlock(&acpi_aml_io.lock);
    178	return ret;
    179}
    180
    181static bool acpi_aml_user_readable(void)
    182{
    183	bool ret;
    184
    185	mutex_lock(&acpi_aml_io.lock);
    186	ret = !__acpi_aml_access_ok(ACPI_AML_OUT_USER) ||
    187	      __acpi_aml_readable(&acpi_aml_io.out_crc, ACPI_AML_OUT_USER);
    188	mutex_unlock(&acpi_aml_io.lock);
    189	return ret;
    190}
    191
    192static bool acpi_aml_user_writable(void)
    193{
    194	bool ret;
    195
    196	mutex_lock(&acpi_aml_io.lock);
    197	ret = !__acpi_aml_access_ok(ACPI_AML_IN_USER) ||
    198	      __acpi_aml_writable(&acpi_aml_io.in_crc, ACPI_AML_IN_USER);
    199	mutex_unlock(&acpi_aml_io.lock);
    200	return ret;
    201}
    202
    203static int acpi_aml_lock_write(struct circ_buf *circ, unsigned long flag)
    204{
    205	int ret = 0;
    206
    207	mutex_lock(&acpi_aml_io.lock);
    208	if (!__acpi_aml_access_ok(flag)) {
    209		ret = -EFAULT;
    210		goto out;
    211	}
    212	if (!__acpi_aml_writable(circ, flag)) {
    213		ret = -EAGAIN;
    214		goto out;
    215	}
    216	acpi_aml_io.flags |= flag;
    217out:
    218	mutex_unlock(&acpi_aml_io.lock);
    219	return ret;
    220}
    221
    222static int acpi_aml_lock_read(struct circ_buf *circ, unsigned long flag)
    223{
    224	int ret = 0;
    225
    226	mutex_lock(&acpi_aml_io.lock);
    227	if (!__acpi_aml_access_ok(flag)) {
    228		ret = -EFAULT;
    229		goto out;
    230	}
    231	if (!__acpi_aml_readable(circ, flag)) {
    232		ret = -EAGAIN;
    233		goto out;
    234	}
    235	acpi_aml_io.flags |= flag;
    236out:
    237	mutex_unlock(&acpi_aml_io.lock);
    238	return ret;
    239}
    240
    241static void acpi_aml_unlock_fifo(unsigned long flag, bool wakeup)
    242{
    243	mutex_lock(&acpi_aml_io.lock);
    244	acpi_aml_io.flags &= ~flag;
    245	if (wakeup)
    246		wake_up_interruptible(&acpi_aml_io.wait);
    247	mutex_unlock(&acpi_aml_io.lock);
    248}
    249
    250static int acpi_aml_write_kern(const char *buf, int len)
    251{
    252	int ret;
    253	struct circ_buf *crc = &acpi_aml_io.out_crc;
    254	int n;
    255	char *p;
    256
    257	ret = acpi_aml_lock_write(crc, ACPI_AML_OUT_KERN);
    258	if (ret < 0)
    259		return ret;
    260	/* sync tail before inserting logs */
    261	smp_mb();
    262	p = &crc->buf[crc->head];
    263	n = min(len, circ_space_to_end(crc));
    264	memcpy(p, buf, n);
    265	/* sync head after inserting logs */
    266	smp_wmb();
    267	crc->head = (crc->head + n) & (ACPI_AML_BUF_SIZE - 1);
    268	acpi_aml_unlock_fifo(ACPI_AML_OUT_KERN, true);
    269	return n;
    270}
    271
    272static int acpi_aml_readb_kern(void)
    273{
    274	int ret;
    275	struct circ_buf *crc = &acpi_aml_io.in_crc;
    276	char *p;
    277
    278	ret = acpi_aml_lock_read(crc, ACPI_AML_IN_KERN);
    279	if (ret < 0)
    280		return ret;
    281	/* sync head before removing cmds */
    282	smp_rmb();
    283	p = &crc->buf[crc->tail];
    284	ret = (int)*p;
    285	/* sync tail before inserting cmds */
    286	smp_mb();
    287	crc->tail = (crc->tail + 1) & (ACPI_AML_BUF_SIZE - 1);
    288	acpi_aml_unlock_fifo(ACPI_AML_IN_KERN, true);
    289	return ret;
    290}
    291
    292/*
    293 * acpi_aml_write_log() - Capture debugger output
    294 * @msg: the debugger output
    295 *
    296 * This function should be used to implement acpi_os_printf() to filter out
    297 * the debugger output and store the output into the debugger interface
    298 * buffer. Return the size of stored logs or errno.
    299 */
    300static ssize_t acpi_aml_write_log(const char *msg)
    301{
    302	int ret = 0;
    303	int count = 0, size = 0;
    304
    305	if (!acpi_aml_initialized)
    306		return -ENODEV;
    307	if (msg)
    308		count = strlen(msg);
    309	while (count > 0) {
    310again:
    311		ret = acpi_aml_write_kern(msg + size, count);
    312		if (ret == -EAGAIN) {
    313			ret = wait_event_interruptible(acpi_aml_io.wait,
    314				acpi_aml_kern_writable());
    315			/*
    316			 * We need to retry when the condition
    317			 * becomes true.
    318			 */
    319			if (ret == 0)
    320				goto again;
    321			break;
    322		}
    323		if (ret < 0)
    324			break;
    325		size += ret;
    326		count -= ret;
    327	}
    328	return size > 0 ? size : ret;
    329}
    330
    331/*
    332 * acpi_aml_read_cmd() - Capture debugger input
    333 * @msg: the debugger input
    334 * @size: the size of the debugger input
    335 *
    336 * This function should be used to implement acpi_os_get_line() to capture
    337 * the debugger input commands and store the input commands into the
    338 * debugger interface buffer. Return the size of stored commands or errno.
    339 */
    340static ssize_t acpi_aml_read_cmd(char *msg, size_t count)
    341{
    342	int ret = 0;
    343	int size = 0;
    344
    345	/*
    346	 * This is ensured by the running fact of the debugger thread
    347	 * unless a bug is introduced.
    348	 */
    349	BUG_ON(!acpi_aml_initialized);
    350	while (count > 0) {
    351again:
    352		/*
    353		 * Check each input byte to find the end of the command.
    354		 */
    355		ret = acpi_aml_readb_kern();
    356		if (ret == -EAGAIN) {
    357			ret = wait_event_interruptible(acpi_aml_io.wait,
    358				acpi_aml_kern_readable());
    359			/*
    360			 * We need to retry when the condition becomes
    361			 * true.
    362			 */
    363			if (ret == 0)
    364				goto again;
    365		}
    366		if (ret < 0)
    367			break;
    368		*(msg + size) = (char)ret;
    369		size++;
    370		count--;
    371		if (ret == '\n') {
    372			/*
    373			 * acpi_os_get_line() requires a zero terminated command
    374			 * string.
    375			 */
    376			*(msg + size - 1) = '\0';
    377			break;
    378		}
    379	}
    380	return size > 0 ? size : ret;
    381}
    382
    383static int acpi_aml_thread(void *unused)
    384{
    385	acpi_osd_exec_callback function = NULL;
    386	void *context;
    387
    388	mutex_lock(&acpi_aml_io.lock);
    389	if (acpi_aml_io.function) {
    390		acpi_aml_io.usages++;
    391		function = acpi_aml_io.function;
    392		context = acpi_aml_io.context;
    393	}
    394	mutex_unlock(&acpi_aml_io.lock);
    395
    396	if (function)
    397		function(context);
    398
    399	mutex_lock(&acpi_aml_io.lock);
    400	acpi_aml_io.usages--;
    401	if (!__acpi_aml_used()) {
    402		acpi_aml_io.thread = NULL;
    403		wake_up(&acpi_aml_io.wait);
    404	}
    405	mutex_unlock(&acpi_aml_io.lock);
    406
    407	return 0;
    408}
    409
    410/*
    411 * acpi_aml_create_thread() - Create AML debugger thread
    412 * @function: the debugger thread callback
    413 * @context: the context to be passed to the debugger thread
    414 *
    415 * This function should be used to implement acpi_os_execute() which is
    416 * used by the ACPICA debugger to create the debugger thread.
    417 */
    418static int acpi_aml_create_thread(acpi_osd_exec_callback function, void *context)
    419{
    420	struct task_struct *t;
    421
    422	mutex_lock(&acpi_aml_io.lock);
    423	acpi_aml_io.function = function;
    424	acpi_aml_io.context = context;
    425	mutex_unlock(&acpi_aml_io.lock);
    426
    427	t = kthread_create(acpi_aml_thread, NULL, "aml");
    428	if (IS_ERR(t)) {
    429		pr_err("Failed to create AML debugger thread.\n");
    430		return PTR_ERR(t);
    431	}
    432
    433	mutex_lock(&acpi_aml_io.lock);
    434	acpi_aml_io.thread = t;
    435	acpi_set_debugger_thread_id((acpi_thread_id)(unsigned long)t);
    436	wake_up_process(t);
    437	mutex_unlock(&acpi_aml_io.lock);
    438	return 0;
    439}
    440
    441static int acpi_aml_wait_command_ready(bool single_step,
    442				       char *buffer, size_t length)
    443{
    444	acpi_status status;
    445
    446	if (single_step)
    447		acpi_os_printf("\n%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT);
    448	else
    449		acpi_os_printf("\n%1c ", ACPI_DEBUGGER_COMMAND_PROMPT);
    450
    451	status = acpi_os_get_line(buffer, length, NULL);
    452	if (ACPI_FAILURE(status))
    453		return -EINVAL;
    454	return 0;
    455}
    456
    457static int acpi_aml_notify_command_complete(void)
    458{
    459	return 0;
    460}
    461
    462static int acpi_aml_open(struct inode *inode, struct file *file)
    463{
    464	int ret = 0;
    465	acpi_status status;
    466
    467	mutex_lock(&acpi_aml_io.lock);
    468	/*
    469	 * The debugger interface is being closed, no new user is allowed
    470	 * during this period.
    471	 */
    472	if (acpi_aml_io.flags & ACPI_AML_CLOSED) {
    473		ret = -EBUSY;
    474		goto err_lock;
    475	}
    476	if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
    477		/*
    478		 * Only one reader is allowed to initiate the debugger
    479		 * thread.
    480		 */
    481		if (acpi_aml_active_reader) {
    482			ret = -EBUSY;
    483			goto err_lock;
    484		} else {
    485			pr_debug("Opening debugger reader.\n");
    486			acpi_aml_active_reader = file;
    487		}
    488	} else {
    489		/*
    490		 * No writer is allowed unless the debugger thread is
    491		 * ready.
    492		 */
    493		if (!(acpi_aml_io.flags & ACPI_AML_OPENED)) {
    494			ret = -ENODEV;
    495			goto err_lock;
    496		}
    497	}
    498	if (acpi_aml_active_reader == file) {
    499		pr_debug("Opening debugger interface.\n");
    500		mutex_unlock(&acpi_aml_io.lock);
    501
    502		pr_debug("Initializing debugger thread.\n");
    503		status = acpi_initialize_debugger();
    504		if (ACPI_FAILURE(status)) {
    505			pr_err("Failed to initialize debugger.\n");
    506			ret = -EINVAL;
    507			goto err_exit;
    508		}
    509		pr_debug("Debugger thread initialized.\n");
    510
    511		mutex_lock(&acpi_aml_io.lock);
    512		acpi_aml_io.flags |= ACPI_AML_OPENED;
    513		acpi_aml_io.out_crc.head = acpi_aml_io.out_crc.tail = 0;
    514		acpi_aml_io.in_crc.head = acpi_aml_io.in_crc.tail = 0;
    515		pr_debug("Debugger interface opened.\n");
    516	}
    517	acpi_aml_io.users++;
    518err_lock:
    519	if (ret < 0) {
    520		if (acpi_aml_active_reader == file)
    521			acpi_aml_active_reader = NULL;
    522	}
    523	mutex_unlock(&acpi_aml_io.lock);
    524err_exit:
    525	return ret;
    526}
    527
    528static int acpi_aml_release(struct inode *inode, struct file *file)
    529{
    530	mutex_lock(&acpi_aml_io.lock);
    531	acpi_aml_io.users--;
    532	if (file == acpi_aml_active_reader) {
    533		pr_debug("Closing debugger reader.\n");
    534		acpi_aml_active_reader = NULL;
    535
    536		pr_debug("Closing debugger interface.\n");
    537		acpi_aml_io.flags |= ACPI_AML_CLOSED;
    538
    539		/*
    540		 * Wake up all user space/kernel space blocked
    541		 * readers/writers.
    542		 */
    543		wake_up_interruptible(&acpi_aml_io.wait);
    544		mutex_unlock(&acpi_aml_io.lock);
    545		/*
    546		 * Wait all user space/kernel space readers/writers to
    547		 * stop so that ACPICA command loop of the debugger thread
    548		 * should fail all its command line reads after this point.
    549		 */
    550		wait_event(acpi_aml_io.wait, !acpi_aml_busy());
    551
    552		/*
    553		 * Then we try to terminate the debugger thread if it is
    554		 * not terminated.
    555		 */
    556		pr_debug("Terminating debugger thread.\n");
    557		acpi_terminate_debugger();
    558		wait_event(acpi_aml_io.wait, !acpi_aml_used());
    559		pr_debug("Debugger thread terminated.\n");
    560
    561		mutex_lock(&acpi_aml_io.lock);
    562		acpi_aml_io.flags &= ~ACPI_AML_OPENED;
    563	}
    564	if (acpi_aml_io.users == 0) {
    565		pr_debug("Debugger interface closed.\n");
    566		acpi_aml_io.flags &= ~ACPI_AML_CLOSED;
    567	}
    568	mutex_unlock(&acpi_aml_io.lock);
    569	return 0;
    570}
    571
    572static int acpi_aml_read_user(char __user *buf, int len)
    573{
    574	int ret;
    575	struct circ_buf *crc = &acpi_aml_io.out_crc;
    576	int n;
    577	char *p;
    578
    579	ret = acpi_aml_lock_read(crc, ACPI_AML_OUT_USER);
    580	if (ret < 0)
    581		return ret;
    582	/* sync head before removing logs */
    583	smp_rmb();
    584	p = &crc->buf[crc->tail];
    585	n = min(len, circ_count_to_end(crc));
    586	if (copy_to_user(buf, p, n)) {
    587		ret = -EFAULT;
    588		goto out;
    589	}
    590	/* sync tail after removing logs */
    591	smp_mb();
    592	crc->tail = (crc->tail + n) & (ACPI_AML_BUF_SIZE - 1);
    593	ret = n;
    594out:
    595	acpi_aml_unlock_fifo(ACPI_AML_OUT_USER, ret >= 0);
    596	return ret;
    597}
    598
    599static ssize_t acpi_aml_read(struct file *file, char __user *buf,
    600			     size_t count, loff_t *ppos)
    601{
    602	int ret = 0;
    603	int size = 0;
    604
    605	if (!count)
    606		return 0;
    607	if (!access_ok(buf, count))
    608		return -EFAULT;
    609
    610	while (count > 0) {
    611again:
    612		ret = acpi_aml_read_user(buf + size, count);
    613		if (ret == -EAGAIN) {
    614			if (file->f_flags & O_NONBLOCK)
    615				break;
    616			else {
    617				ret = wait_event_interruptible(acpi_aml_io.wait,
    618					acpi_aml_user_readable());
    619				/*
    620				 * We need to retry when the condition
    621				 * becomes true.
    622				 */
    623				if (ret == 0)
    624					goto again;
    625			}
    626		}
    627		if (ret < 0) {
    628			if (!acpi_aml_running())
    629				ret = 0;
    630			break;
    631		}
    632		if (ret) {
    633			size += ret;
    634			count -= ret;
    635			*ppos += ret;
    636			break;
    637		}
    638	}
    639	return size > 0 ? size : ret;
    640}
    641
    642static int acpi_aml_write_user(const char __user *buf, int len)
    643{
    644	int ret;
    645	struct circ_buf *crc = &acpi_aml_io.in_crc;
    646	int n;
    647	char *p;
    648
    649	ret = acpi_aml_lock_write(crc, ACPI_AML_IN_USER);
    650	if (ret < 0)
    651		return ret;
    652	/* sync tail before inserting cmds */
    653	smp_mb();
    654	p = &crc->buf[crc->head];
    655	n = min(len, circ_space_to_end(crc));
    656	if (copy_from_user(p, buf, n)) {
    657		ret = -EFAULT;
    658		goto out;
    659	}
    660	/* sync head after inserting cmds */
    661	smp_wmb();
    662	crc->head = (crc->head + n) & (ACPI_AML_BUF_SIZE - 1);
    663	ret = n;
    664out:
    665	acpi_aml_unlock_fifo(ACPI_AML_IN_USER, ret >= 0);
    666	return n;
    667}
    668
    669static ssize_t acpi_aml_write(struct file *file, const char __user *buf,
    670			      size_t count, loff_t *ppos)
    671{
    672	int ret = 0;
    673	int size = 0;
    674
    675	if (!count)
    676		return 0;
    677	if (!access_ok(buf, count))
    678		return -EFAULT;
    679
    680	while (count > 0) {
    681again:
    682		ret = acpi_aml_write_user(buf + size, count);
    683		if (ret == -EAGAIN) {
    684			if (file->f_flags & O_NONBLOCK)
    685				break;
    686			else {
    687				ret = wait_event_interruptible(acpi_aml_io.wait,
    688					acpi_aml_user_writable());
    689				/*
    690				 * We need to retry when the condition
    691				 * becomes true.
    692				 */
    693				if (ret == 0)
    694					goto again;
    695			}
    696		}
    697		if (ret < 0) {
    698			if (!acpi_aml_running())
    699				ret = 0;
    700			break;
    701		}
    702		if (ret) {
    703			size += ret;
    704			count -= ret;
    705			*ppos += ret;
    706		}
    707	}
    708	return size > 0 ? size : ret;
    709}
    710
    711static __poll_t acpi_aml_poll(struct file *file, poll_table *wait)
    712{
    713	__poll_t masks = 0;
    714
    715	poll_wait(file, &acpi_aml_io.wait, wait);
    716	if (acpi_aml_user_readable())
    717		masks |= EPOLLIN | EPOLLRDNORM;
    718	if (acpi_aml_user_writable())
    719		masks |= EPOLLOUT | EPOLLWRNORM;
    720
    721	return masks;
    722}
    723
    724static const struct file_operations acpi_aml_operations = {
    725	.read		= acpi_aml_read,
    726	.write		= acpi_aml_write,
    727	.poll		= acpi_aml_poll,
    728	.open		= acpi_aml_open,
    729	.release	= acpi_aml_release,
    730	.llseek		= generic_file_llseek,
    731};
    732
    733static const struct acpi_debugger_ops acpi_aml_debugger = {
    734	.create_thread		 = acpi_aml_create_thread,
    735	.read_cmd		 = acpi_aml_read_cmd,
    736	.write_log		 = acpi_aml_write_log,
    737	.wait_command_ready	 = acpi_aml_wait_command_ready,
    738	.notify_command_complete = acpi_aml_notify_command_complete,
    739};
    740
    741static int __init acpi_aml_init(void)
    742{
    743	int ret;
    744
    745	if (acpi_disabled)
    746		return -ENODEV;
    747
    748	/* Initialize AML IO interface */
    749	mutex_init(&acpi_aml_io.lock);
    750	init_waitqueue_head(&acpi_aml_io.wait);
    751	acpi_aml_io.out_crc.buf = acpi_aml_io.out_buf;
    752	acpi_aml_io.in_crc.buf = acpi_aml_io.in_buf;
    753
    754	acpi_aml_dentry = debugfs_create_file("acpidbg",
    755					      S_IFREG | S_IRUGO | S_IWUSR,
    756					      acpi_debugfs_dir, NULL,
    757					      &acpi_aml_operations);
    758
    759	ret = acpi_register_debugger(THIS_MODULE, &acpi_aml_debugger);
    760	if (ret) {
    761		debugfs_remove(acpi_aml_dentry);
    762		acpi_aml_dentry = NULL;
    763		return ret;
    764	}
    765
    766	acpi_aml_initialized = true;
    767	return 0;
    768}
    769
    770static void __exit acpi_aml_exit(void)
    771{
    772	if (acpi_aml_initialized) {
    773		acpi_unregister_debugger(&acpi_aml_debugger);
    774		debugfs_remove(acpi_aml_dentry);
    775		acpi_aml_dentry = NULL;
    776		acpi_aml_initialized = false;
    777	}
    778}
    779
    780module_init(acpi_aml_init);
    781module_exit(acpi_aml_exit);
    782
    783MODULE_AUTHOR("Lv Zheng");
    784MODULE_DESCRIPTION("ACPI debugger userspace IO driver");
    785MODULE_LICENSE("GPL");