diff --git a/drivers/cartesi/Kconfig b/drivers/cartesi/Kconfig index b1dcb90995f7..6df6e546dac2 100644 --- a/drivers/cartesi/Kconfig +++ b/drivers/cartesi/Kconfig @@ -14,14 +14,12 @@ config CARTESI_YIELD_DRIVER help Cartesi Machine Yield Device -config CARTESI_ROLLUP_DRIVER - bool "Cartesi Machine Rollup Device" +config CARTESI_MACHINE_IO_DRIVER + bool "Cartesi Machine IO Device" depends on CARTESI_MACHINE - depends on CRYPTO_KECCAK default y help - Cartesi Machine Rollup Device - + Cartesi Machine IO Device config CARTESI_HALT_ON_PANIC bool "Halt machine on kernel panic" diff --git a/drivers/cartesi/Makefile b/drivers/cartesi/Makefile index f601cd315347..770e45f204ea 100644 --- a/drivers/cartesi/Makefile +++ b/drivers/cartesi/Makefile @@ -1,2 +1 @@ -obj-$(CONFIG_CARTESI_YIELD_DRIVER) += yield.o libyield.o -obj-$(CONFIG_CARTESI_ROLLUP_DRIVER) += rollup.o libyield.o libstream256.o +obj-$(CONFIG_CARTESI_MACHINE_IO_DRIVER) += cmio.o diff --git a/drivers/cartesi/cmio.c b/drivers/cartesi/cmio.c new file mode 100644 index 000000000000..d3e225fece3f --- /dev/null +++ b/drivers/cartesi/cmio.c @@ -0,0 +1,241 @@ +////// SPDX-License-Identifier: GPL-2.0 +/* + * Cartesi cmio device. + * Copyright (C) 2023 Cartesi Machine reference unit + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEVICE_NAME "cmio" +#define MODULE_DESC "Cartesi Machine " DEVICE_NAME " device" + +#define SBI_YIELD 9 + +struct cmio_device { + struct platform_device *pdev; + struct miscdevice mdev; + struct cmio_setup bufs; + atomic_t single_user_lock; +}; + +static struct cmio_device *to_cmio_device(struct file *file) +{ + struct miscdevice *dev = file->private_data; + return container_of(dev, struct cmio_device, mdev); +} + +static long cmio_ioctl_setup(struct cmio_device *me, unsigned long arg) +{ + if (copy_to_user((void __user *)arg, &me->bufs, sizeof me->bufs)) + return -EFAULT; + + return 0; +} + +static long cmio_ioctl_yield(struct cmio_device *me, unsigned long arg) +{ + __u64 req = 0, + rep = 0; + + if (copy_from_user(&req, (void __user *)arg, sizeof req)) + return -EFAULT; + + rep = sbi_ecall(SBI_YIELD, 0, req, 0, 0, 0, 0, 0).value; + + if (copy_to_user((void __user *)arg, &rep, sizeof rep)) + return -EFAULT; + + return 0; +} + +/* + * We enforce only one user at a time here with the open/release. + */ +static int cmio_open(struct inode *inode, struct file *file) +{ + struct cmio_device *cmio = to_cmio_device(file); + if (!cmio) + return -EBADF; + + if (!atomic_inc_and_test(&cmio->single_user_lock)) { + atomic_dec(&cmio->single_user_lock); + return -EBUSY; + } + return 0; +} + +static int cmio_release(struct inode *inode, struct file *file) +{ + struct cmio_device *cmio = to_cmio_device(file); + if (!cmio) + return -EBADF; + + atomic_dec(&cmio->single_user_lock); + return 0; +} + +static long cmio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct cmio_device *cmio = to_cmio_device(file); + if (!cmio) + return -EBADF; + + switch (cmd) { + case IOCTL_CMIO_SETUP: + return cmio_ioctl_setup(cmio, arg); + case IOCTL_CMIO_YIELD: + return cmio_ioctl_yield(cmio, arg); + } + return -ENOIOCTLCMD; +} + +static int cmio_mmap(struct file *file, struct vm_area_struct *vma) +{ + __u64 vma_size; + struct cmio_device *cmio = to_cmio_device(file); + if (!cmio) + return -EBADF; + + vma_size = vma->vm_end - vma->vm_start; + if (!((vma->vm_start == cmio->bufs.tx.data && vma_size == cmio->bufs.tx.length) + || (vma->vm_start == cmio->bufs.rx.data && vma_size == cmio->bufs.rx.length))) + return -EINVAL; + + return remap_pfn_range(vma, + vma->vm_start, + vma->vm_start >> PAGE_SHIFT, + vma_size, + vma->vm_page_prot); +} + +static const struct file_operations cmio_fileops = { + .open = cmio_open, + .release = cmio_release, + .unlocked_ioctl = cmio_ioctl, + .mmap = cmio_mmap, + .owner = THIS_MODULE, +}; + +static int setup_buffer(struct device_node *parent, const char *name, struct cmio_buffer *buf) +{ + u64 xs[2]; + int rc = -EIO; + struct device_node *node = NULL; + + if (!(node = of_find_node_by_name(parent, name))) + goto leave; + if (of_property_read_u64_array(node, "reg", xs, 2)) + goto leave; + if (!(buf->data = xs[0])) + goto leave; + if (!(buf->length = xs[1])) + goto leave; + rc = 0; +leave: + of_node_put(node); + return rc; +} + +static int check_yield_automatic_and_manual(struct device_node *node) +{ + return !(of_property_read_bool(node, "automatic") + && of_property_read_bool(node, "manual")); +} + +static int setup_io(struct cmio_device *cmio) +{ + int rc = -EIO; + struct device_node *cmio_node = NULL, + *yield_node = NULL; + + if (!(cmio_node = of_find_node_by_path("/cmio")) + || setup_buffer(cmio_node, "tx_buffer", &cmio->bufs.tx) + || setup_buffer(cmio_node, "rx_buffer", &cmio->bufs.rx)) + goto leave; + + if (!(yield_node = of_find_node_by_path("/yield")) + || check_yield_automatic_and_manual(yield_node)) + goto leave; + rc = 0; +leave: + of_node_put(yield_node); + of_node_put(cmio_node); + return rc; +} + +static int cmio_driver_probe(struct platform_device *pdev) +{ + int rc; + struct cmio_device *cmio; + + cmio = devm_kzalloc(&pdev->dev, sizeof(*cmio), GFP_KERNEL); + if (!cmio) + return -ENOMEM; + + atomic_set(&cmio->single_user_lock, -1); + cmio->mdev.minor = MISC_DYNAMIC_MINOR; + cmio->mdev.name = DEVICE_NAME; + cmio->mdev.fops = &cmio_fileops; + rc = misc_register(&cmio->mdev); + if (rc) { + dev_err(&pdev->dev, "failed to register miscdevice\n"); + goto leave; + } + + rc = setup_io(cmio); + if (rc) { + dev_err(&pdev->dev, "failed to parse device tree\n"); + goto deregister; + } + + platform_set_drvdata(pdev, cmio); + cmio->pdev = pdev; + + pr_info(MODULE_DESC ": Module loaded\n"); + return 0; + +deregister: + misc_deregister(&cmio->mdev); +leave: + return rc; +} + +static int cmio_driver_remove(struct platform_device *pdev) +{ + struct cmio_device *cmio = platform_get_drvdata(pdev); + misc_deregister(&cmio->mdev); + dev_info(&pdev->dev, "unregistered\n"); + return 0; +} + +static const struct of_device_id cmio_match[] = { + {.compatible = "ctsi-cmio",}, {}, +}; +MODULE_DEVICE_TABLE(of, cmio_match); + +static struct platform_driver cmio_driver = { + .driver = { + .name = DEVICE_NAME, + .of_match_table = cmio_match, + }, + .probe = cmio_driver_probe, + .remove = cmio_driver_remove, +}; + +module_platform_driver(cmio_driver); + +MODULE_DESCRIPTION(MODULE_DESC); +MODULE_LICENSE("GPL"); diff --git a/drivers/cartesi/libstream256.c b/drivers/cartesi/libstream256.c deleted file mode 100644 index 9ffd516aca73..000000000000 --- a/drivers/cartesi/libstream256.c +++ /dev/null @@ -1,107 +0,0 @@ -#include -#include -#include "libstream256.h" - -static bool in_bounds(const struct stream256 *me, size_t bytes) -{ - return me->length - me->offset >= bytes; -} - -static size_t align256(size_t n) -{ - return PTR_ALIGN(n, sizeof(union be256)); -} - -static void pad(struct stream256 *me, size_t n) -{ - size_t misaligned = align256(n) - n; - - if (misaligned) { - memset(me->data + me->offset, 0, misaligned); - me->offset += misaligned; - } -} - -void stream256_reset(struct stream256 *me) -{ - me->offset = 0; -} - -int stream256_encode_u64(struct stream256 *me, uint64_t x) -{ - union be256 u; - - be256_from_u64(&u, x); - if (!in_bounds(me, sizeof(u))) - return -ENOBUFS; - memcpy(me->data + me->offset, u.data, sizeof(u)); - me->offset += sizeof(u); - - return 0; -} - -int stream256_encode_address(struct stream256 *me, uint8_t *p, size_t n) -{ - if (!in_bounds(me, align256(n))) - return -ENOBUFS; - pad(me, n); - memcpy(me->data + me->offset, p, n); - me->offset += n; - - return 0; -} - -int stream256_encode_buf(struct stream256 *me, uint8_t *p, size_t n) -{ - if (!in_bounds(me, align256(n))) - return -ENOBUFS; - memcpy(me->data + me->offset, p, n); - me->offset += n; - pad(me, n); - - return 0; -} - -int stream256_encode_ubuf(struct stream256 *me, uint8_t *p, size_t n) -{ - int ret; - - if (!in_bounds(me, align256(n))) - return -ENOBUFS; - if ((ret = copy_from_user(me->data + me->offset, p, n))) - return ret; - me->offset += n; - pad(me, n); - - return 0; -} - -int stream256_encode_keccak(struct shash_desc *keccak, - const struct stream256 *me, struct stream256 *hash, uint64_t *index) -{ - if (!in_bounds(hash, align256(sizeof(union be256)))) - return -ENOBUFS; - crypto_shash_init(keccak); - crypto_shash_update(keccak, me->data, me->offset); - crypto_shash_final(keccak, hash->data + hash->offset); - if (index) - *index = hash->offset / sizeof(union be256); - hash->offset += sizeof(union be256); - return 0; -} - -void be256_from_u64(union be256 *me, uint64_t x) -{ - me->be64[0] = 0; - me->be64[1] = 0; - me->be64[2] = 0; - me->be64[3] = cpu_to_be64(x); -} - -int be256_to_u64(union be256 *me, uint64_t *x) -{ - if (me->be64[0] || me->be64[1] || me->be64[2]) - return -EDOM; - *x = be64_to_cpu(me->be64[3]); - return 0; -} diff --git a/drivers/cartesi/libstream256.h b/drivers/cartesi/libstream256.h deleted file mode 100644 index bf05d13310a6..000000000000 --- a/drivers/cartesi/libstream256.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef LIBSTREAM_H -#define LIBSTREAM_H -#include -#include - -struct stream256 { - u8 *data; - u64 offset, length; -}; - -union be256 { - __be64 be64[4]; - __be32 be32[8]; - __be16 be16[16]; - u8 data[32]; -}; - -typedef int (*stream256_encode_buf_t)(struct stream256 *me, u8 *p, size_t n); - -void stream256_reset (struct stream256 *me); -int stream256_encode_u64 (struct stream256 *me, u64 x); -int stream256_encode_address(struct stream256 *me, u8 *p, size_t n); -int stream256_encode_buf (struct stream256 *me, u8 *p, size_t n); -int stream256_encode_ubuf(struct stream256 *me, u8 *p, size_t n); -int stream256_encode_keccak(struct shash_desc *keccak, - const struct stream256 *me, struct stream256 *hash, uint64_t*index); - -void be256_from_u64(union be256 *me, uint64_t x); -int be256_to_u64(union be256 *me, uint64_t *x); - -#endif /* LIBSTREAM_H */ diff --git a/drivers/cartesi/libyield.c b/drivers/cartesi/libyield.c deleted file mode 100644 index cedbcdc8245f..000000000000 --- a/drivers/cartesi/libyield.c +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include -#include "libyield.h" - -#define SBI_YIELD 9 - -static int _yield_validate(u64 dev, u64 cmd, u64 reason) -{ - if (dev != HTIF_DEVICE_YIELD) { - return -EINVAL; - } - - if (cmd != HTIF_YIELD_MANUAL && - cmd != HTIF_YIELD_AUTOMATIC) { - return -EINVAL; - } - - if (reason != HTIF_YIELD_REASON_PROGRESS && - reason != HTIF_YIELD_REASON_RX_ACCEPTED && - reason != HTIF_YIELD_REASON_RX_REJECTED && - reason != HTIF_YIELD_REASON_TX_VOUCHER && - reason != HTIF_YIELD_REASON_TX_NOTICE && - reason != HTIF_YIELD_REASON_TX_REPORT && - reason != HTIF_YIELD_REASON_TX_EXCEPTION) { - return -EINVAL; - } - - return 0; -} - -static u64 _yield_pack(u64 cmd, u64 reason, u64 data) -{ - return ((u64)HTIF_DEVICE_YIELD << 56) - | ((u64)cmd << 56 >> 8) - | ((u64)reason << 48 >> 16) - | ((u64)data << 32 >> 32) - ; -} - -static struct yield_request _yield_unpack(u64 packed) -{ - struct yield_request out = { - (u64)packed >> 56, - (u64)packed << 8 >> 56, - (u64)packed << 16 >> 48, - (u64)packed << 32 >> 32, - }; - return out; -} - -int cartesi_yield_validate(struct yield_request *req) -{ - return req->dev != HTIF_DEVICE_YIELD? -EINVAL: - _yield_validate(req->dev, req->cmd, req->reason); -} - -int cartesi_yield(u64 cmd, u64 reason, u64 data, struct yield_request *rep) -{ - int ret; - struct sbiret sbiret; - u64 tohost; - - if ((ret = _yield_validate(HTIF_DEVICE_YIELD, cmd, reason))) - return ret; - - tohost = _yield_pack(cmd, reason, data); - sbiret = sbi_ecall(SBI_YIELD, 0, tohost, 0, 0, 0, 0, 0); - *rep = _yield_unpack(sbiret.value); - return _yield_validate(rep->dev, rep->cmd, rep->reason); -} diff --git a/drivers/cartesi/libyield.h b/drivers/cartesi/libyield.h deleted file mode 100644 index 562962cfcecf..000000000000 --- a/drivers/cartesi/libyield.h +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Cartesi yield device. - * Copyright (C) 2020-2021 Cartesi Pte. Ltd. - */ -#ifndef LIBYIELD_H -#define LIBYIELD_H -#include - -int cartesi_yield_validate(struct yield_request *rep); -int cartesi_yield(u64 mode, u64 reason, u64 data, struct yield_request *reply); - -#endif /* LIBYIELD_H */ diff --git a/drivers/cartesi/rollup.c b/drivers/cartesi/rollup.c deleted file mode 100644 index 6d80cbb3a58e..000000000000 --- a/drivers/cartesi/rollup.c +++ /dev/null @@ -1,567 +0,0 @@ -////// SPDX-License-Identifier: GPL-2.0 -/* - * Cartesi rollup device. - * Copyright (C) 2021 Cartesi Pte. Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "libstream256.h" -#include "libyield.h" -#include - -#define DEVICE_NAME "rollup" -#define FDT_ROLLUP_PATH "/rollup" -#define MODULE_DESC "Cartesi Machine " DEVICE_NAME " device" - -#define CARTESI_ROLLUP_INITIAL_STATE (-1) - -/* NOTE: keep in sync with node_paths */ -#define TX_BUFFER_INDEX 0 -#define RX_BUFFER_INDEX 1 -#define INPUT_METADATA_INDEX 2 -#define VOUCHER_HASHES_INDEX 3 -#define NOTICE_HASHES_INDEX 4 - -static const char *node_paths[] = { - "tx_buffer", - "rx_buffer", - "input_metadata", - "voucher_hashes", - "notice_hashes", -}; - -static atomic_t rollup_probe_once = ATOMIC_INIT(1); - -struct rollup_device { - struct platform_device *pdev; - struct miscdevice mdev; - struct shash_desc *keccak; - struct mutex lock; - atomic_t rollup_status; - int next_request_type; - struct stream256 buffers[ARRAY_SIZE(node_paths)]; -}; - -struct rx_header { - union be256 offset; - union be256 length; -}; - -struct input_metadata_header { - uint8_t padding[sizeof(union be256) - CARTESI_ROLLUP_ADDRESS_SIZE]; - uint8_t msg_sender[CARTESI_ROLLUP_ADDRESS_SIZE]; - union be256 blocknumber; - union be256 timestamp; - union be256 epoch_number; - union be256 input_number; -}; - -static struct rollup_device *to_rollup_device(struct file *file) -{ - struct miscdevice *dev = file->private_data; - return container_of(dev, struct rollup_device, mdev); -} - -static long rollup_ioctl_finish(struct rollup_device *rollup, unsigned long arg) -{ - long i, ret; - u64 rx_length, reason; - struct rollup_finish finish; - struct stream256 *rx = &rollup->buffers[RX_BUFFER_INDEX]; - struct yield_request rep; - - // NOTE: pointer is known to be aligned - struct rx_header *rx_header = (void *)rx->data; - - if ((ret = copy_from_user(&finish, (void __user*)arg, sizeof(finish)))) { - return -EFAULT; - } - - reason = finish.accept_previous_request? - HTIF_YIELD_REASON_RX_ACCEPTED: - HTIF_YIELD_REASON_RX_REJECTED; - - if (mutex_lock_interruptible(&rollup->lock)) - return -ERESTARTSYS; - - if ((ret = cartesi_yield(HTIF_YIELD_MANUAL, reason, 0, &rep))) { - ret = -EIO; - goto unlock; - } - - if (rep.data != CARTESI_ROLLUP_ADVANCE_STATE && - rep.data != CARTESI_ROLLUP_INSPECT_STATE) { - ret = -EOPNOTSUPP; - goto unlock; - } - rollup->next_request_type = rep.data; - finish.next_request_type = rep.data; - - if ((ret = be256_to_u64(&rx_header->length, &rx_length))) - goto unlock; - - for (i = 0; i < ARRAY_SIZE(node_paths); ++i) - stream256_reset(&rollup->buffers[i]); - - mutex_unlock(&rollup->lock); - - finish.next_request_payload_length = rx_length; - if ((ret = copy_to_user((void __user*)arg, &finish, sizeof(finish)))) - return -EFAULT; - - return 0; -unlock: - mutex_unlock(&rollup->lock); - return ret; -} - -static long copy_rx(struct rollup_device *rollup, struct rollup_bytes *payload) -{ - long ret; - struct stream256 *rx = &rollup->buffers[RX_BUFFER_INDEX]; - struct rx_header *rxh = (void *)rx->data; - u64 data_length, data_bytes_to_copy; - - if ((ret = be256_to_u64(&rxh->length, &data_length))) - return ret; - - // length we received in `rxh` must fit into `rx` - if (data_length > rx->length - sizeof(*rxh)) - return -EIO; - - // it must also fit into the buffer the user provided - if (data_length > payload->length) - return -ENOBUFS; - - data_bytes_to_copy = min(data_length, payload->length); - return copy_to_user((void __user*)payload->data, rxh + 1, data_bytes_to_copy); -} - -static long rollup_ioctl_read_advance(struct rollup_device *rollup, unsigned long arg) -{ - long ret; - struct stream256 *im = &rollup->buffers[INPUT_METADATA_INDEX]; - struct input_metadata_header *imh = (void *)im->data; - struct rollup_advance_state advance; - - if (rollup->next_request_type != CARTESI_ROLLUP_ADVANCE_STATE) - return -EOPNOTSUPP; - - if ((ret = copy_from_user(&advance, (void __user*)arg, sizeof(advance)))) - return -EFAULT; - - if (mutex_lock_interruptible(&rollup->lock)) - return -ERESTARTSYS; - - if ((ret = copy_rx(rollup, &advance.payload))) { - ret = -EFAULT; - goto unlock; - } - - memcpy(advance.metadata.msg_sender, &imh->msg_sender, sizeof(advance.metadata.msg_sender)); - if ((ret = be256_to_u64(&imh->blocknumber, &advance.metadata.block_number)) || - (ret = be256_to_u64(&imh->timestamp, &advance.metadata.timestamp)) || - (ret = be256_to_u64(&imh->epoch_number, &advance.metadata.epoch_index)) || - (ret = be256_to_u64(&imh->input_number, &advance.metadata.input_index))) { - goto unlock; - } - mutex_unlock(&rollup->lock); - - if ((ret = copy_to_user((void __user*)arg, &advance, sizeof(advance)))) - return -EFAULT; - - return 0; -unlock: - mutex_unlock(&rollup->lock); - return ret; -} - -static long rollup_ioctl_read_inspect(struct rollup_device *rollup, unsigned long arg) -{ - long ret = 0; - struct rollup_inspect_state inspect; - - if (rollup->next_request_type != CARTESI_ROLLUP_INSPECT_STATE) - return -EOPNOTSUPP; - - if ((ret = copy_from_user(&inspect, (void __user*)arg, sizeof(inspect)))) - return -EFAULT; - - if (mutex_lock_interruptible(&rollup->lock)) - return -ERESTARTSYS; - - if ((ret = copy_rx(rollup, &inspect.payload))) { - ret = -EFAULT; - goto unlock; - } - - /* fall-through */ -unlock: - mutex_unlock(&rollup->lock); - return ret; -} - -static long rollup_ioctl_voucher(struct rollup_device *rollup, unsigned long arg) -{ - long ret = 0; - struct rollup_voucher voucher; - struct stream256 *tx = &rollup->buffers[TX_BUFFER_INDEX], - *vh = &rollup->buffers[VOUCHER_HASHES_INDEX]; - struct yield_request rep; - - if (rollup->next_request_type == CARTESI_ROLLUP_INSPECT_STATE) { - dev_warn(&rollup->pdev->dev, "trying to emit a voucher during a inspect\n"); - return -EOPNOTSUPP; - } - - if ((ret = copy_from_user(&voucher, (void __user*)arg, sizeof(voucher)))) { - dev_warn(&rollup->pdev->dev, "failed to read voucher struct\n"); - return -EFAULT; - } - - if (mutex_lock_interruptible(&rollup->lock)) - return -ERESTARTSYS; - - stream256_reset(tx); - if ((ret = stream256_encode_address(tx, voucher.destination, sizeof(voucher.destination))) || - (ret = stream256_encode_u64(tx, 0x40)) || - (ret = stream256_encode_u64(tx, voucher.payload.length)) || - (ret = stream256_encode_ubuf(tx, voucher.payload.data, voucher.payload.length)) || - (ret = stream256_encode_keccak(rollup->keccak, tx, vh, &voucher.index))) { - goto unlock; - } - - if ((ret = cartesi_yield(HTIF_YIELD_AUTOMATIC, HTIF_YIELD_REASON_TX_VOUCHER, 0, &rep))) { - ret = -EIO; - goto unlock; - } - - if ((ret = copy_to_user((void __user*)arg, &voucher, sizeof(voucher)))) { - ret = -EFAULT; - goto unlock; - } - - /* fall-through */ -unlock: - mutex_unlock(&rollup->lock); - return ret; -} - -static long rollup_ioctl_notice(struct rollup_device *rollup, unsigned long arg) -{ - long ret = 0; - struct rollup_notice notice; - struct stream256 *tx = &rollup->buffers[TX_BUFFER_INDEX], - *nh = &rollup->buffers[NOTICE_HASHES_INDEX]; - - struct yield_request rep; - - if (rollup->next_request_type == CARTESI_ROLLUP_INSPECT_STATE) { - dev_warn(&rollup->pdev->dev, "trying to emit a notice during a inspect\n"); - return -EOPNOTSUPP; - } - - if ((ret = copy_from_user(¬ice, (void __user*)arg, sizeof(notice)))) { - dev_warn(&rollup->pdev->dev, "failed to read notice struct\n"); - return -EFAULT; - } - - if (mutex_lock_interruptible(&rollup->lock)) - return -ERESTARTSYS; - - stream256_reset(tx); - if ((ret = stream256_encode_u64(tx, 0x20)) || - (ret = stream256_encode_u64(tx, notice.payload.length)) || - (ret = stream256_encode_ubuf(tx, notice.payload.data, notice.payload.length)) || - (ret = stream256_encode_keccak(rollup->keccak, tx, nh, ¬ice.index))) { - goto unlock; - } - - if ((ret = cartesi_yield(HTIF_YIELD_AUTOMATIC, HTIF_YIELD_REASON_TX_NOTICE, 0, &rep))) { - ret = -EIO; - goto unlock; - } - - if ((ret = copy_to_user((void __user*)arg, ¬ice, sizeof(notice)))) { - ret = -EFAULT; - goto unlock; - } - - /* fall-through */ -unlock: - mutex_unlock(&rollup->lock); - return ret; -} - -static long yield_simple_payload(stream256_encode_buf_t enc, struct stream256 *tx, struct rollup_bytes *payload, u64 cmd, u64 reason) -{ - long ret; - struct yield_request rep; - - stream256_reset(tx); - if ((ret = stream256_encode_u64(tx, 0x20)) || - (ret = stream256_encode_u64(tx, payload->length)) || - (ret = enc(tx, payload->data, payload->length))) { - return ret; - } - - if ((ret = cartesi_yield(cmd, reason, 0, &rep))) { - return -EIO; - } - return 0; -} - -static long rollup_ioctl_report(struct rollup_device *rollup, unsigned long arg) -{ - long ret = 0; - struct rollup_report report; - struct stream256 *tx = &rollup->buffers[TX_BUFFER_INDEX]; - - if ((ret = copy_from_user(&report, (void __user*)arg, sizeof(report)))) { - dev_warn(&rollup->pdev->dev, "failed to read report struct\n"); - return -EFAULT; - } - - if (mutex_lock_interruptible(&rollup->lock)) - return -ERESTARTSYS; - - ret = yield_simple_payload(stream256_encode_ubuf, tx, &report.payload, - HTIF_YIELD_AUTOMATIC, HTIF_YIELD_REASON_TX_REPORT); - - mutex_unlock(&rollup->lock); - return ret; -} - -static long rollup_ioctl_exception(struct rollup_device *rollup, unsigned long arg) -{ - long ret = 0; - struct rollup_exception exception; - struct stream256 *tx = &rollup->buffers[TX_BUFFER_INDEX]; - - if ((ret = copy_from_user(&exception, (void __user*)arg, sizeof(exception)))) { - dev_warn(&rollup->pdev->dev, "failed to read exception struct\n"); - return -EFAULT; - } - - if (mutex_lock_interruptible(&rollup->lock)) - return -ERESTARTSYS; - - ret = yield_simple_payload(stream256_encode_ubuf, tx, &exception.payload, - HTIF_YIELD_MANUAL, HTIF_YIELD_REASON_TX_EXCEPTION); - - mutex_unlock(&rollup->lock); - return ret; -} - -/* - * We enforce only one user at a time here with the open/close. - */ -static int rollup_open(struct inode *inode, struct file *file) -{ - struct rollup_device *rollup; - if ((rollup = to_rollup_device(file)) == NULL) - return -EBADF; - - if (!atomic_dec_and_test(&rollup->rollup_status)) { - atomic_inc(&rollup->rollup_status); - return -EBUSY; - } - return 0; -} - -static int rollup_release(struct inode *inode, struct file *file) -{ - struct rollup_device *rollup; - if ((rollup = to_rollup_device(file)) == NULL) - return -EBADF; - - atomic_inc(&rollup->rollup_status); - return 0; -} - -static long rollup_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct rollup_device *rollup; - - if ((rollup = to_rollup_device(file)) == NULL) - return -EBADF; - if ((rollup->next_request_type == CARTESI_ROLLUP_INITIAL_STATE) && !( - (cmd == IOCTL_ROLLUP_FINISH) || - (cmd == IOCTL_ROLLUP_THROW_EXCEPTION))) { - - int ret; - struct stream256 *tx = &rollup->buffers[TX_BUFFER_INDEX]; - unsigned char msg[] = "first ioctl must be either `finish' or `throw_exception'"; - struct rollup_bytes bytes = {msg, sizeof(msg)-1}; - dev_warn(&rollup->pdev->dev, msg); - if (mutex_lock_interruptible(&rollup->lock)) - return -ERESTARTSYS; - - ret = yield_simple_payload(stream256_encode_buf, tx, &bytes, - HTIF_YIELD_MANUAL, HTIF_YIELD_REASON_TX_EXCEPTION); - - mutex_unlock(&rollup->lock); - return -EBADE; - } - - switch (cmd) { - case IOCTL_ROLLUP_FINISH: - return rollup_ioctl_finish(rollup, arg); - case IOCTL_ROLLUP_READ_ADVANCE_STATE: - return rollup_ioctl_read_advance(rollup, arg); - case IOCTL_ROLLUP_READ_INSPECT_STATE: - return rollup_ioctl_read_inspect(rollup, arg); - case IOCTL_ROLLUP_WRITE_NOTICE: - return rollup_ioctl_notice(rollup, arg); - case IOCTL_ROLLUP_WRITE_REPORT: - return rollup_ioctl_report(rollup, arg); - case IOCTL_ROLLUP_WRITE_VOUCHER: - return rollup_ioctl_voucher(rollup, arg); - case IOCTL_ROLLUP_THROW_EXCEPTION: - return rollup_ioctl_exception(rollup, arg); - } - return -ENOIOCTLCMD; -} - -static const struct file_operations rollup_fileops = { - .open = rollup_open, - .release = rollup_release, - .owner = THIS_MODULE, - .unlocked_ioctl = rollup_ioctl -}; - -static int find_memory_regions(struct rollup_device *rollup) -{ - int i, j, err = 0; - struct device_node *node = of_find_node_by_path(FDT_ROLLUP_PATH); - - for (i = 0; !err && i < ARRAY_SIZE(node_paths); ++i) { - u64 xs[2]; - struct stream256 *bi = &rollup->buffers[i]; - struct device_node *buffer = of_find_node_by_name(node, node_paths[i]); - err = of_property_read_u64_array(buffer, "reg", xs, 2); - - if (xs[0] == 0) - return -ENODEV; - if (xs[1] == 0) - return -EIO; - - if ((bi->data = devm_ioremap(rollup->mdev.this_device, xs[0], xs[1])) == NULL) - return -ENODEV; - bi->length = xs[1]; - bi->offset = 0; - - /* do buffers intersect => malformed IO */ - for (j = 0; j < i; ++j) { - struct stream256 *bj = &rollup->buffers[j]; - if ((bi->data <= bj->data && bj->data < bi->data + bi->length) || - (bj->data <= bi->data && bi->data < bj->data + bj->length)) - return -EIO; - } - } - - return err; -} - -static int rollup_driver_probe(struct platform_device *pdev) -{ - struct rollup_device *rollup; - struct crypto_shash *alg; - int ret = -ENXIO; - - if (!atomic_dec_and_test(&rollup_probe_once)) { - atomic_inc(&rollup_probe_once); - return -EBUSY; - } - - rollup = (struct rollup_device*) kzalloc(sizeof(struct rollup_device), GFP_KERNEL); - if (!rollup) { - dev_err(&pdev->dev, "failed to allocate memory\n"); - return -ENOMEM; - } - - atomic_set(&rollup->rollup_status, 1); - rollup->mdev.minor = MISC_DYNAMIC_MINOR; - rollup->mdev.name = DEVICE_NAME; - rollup->mdev.fops = &rollup_fileops; - if ((ret = misc_register(&rollup->mdev)) != 0) { - dev_err(&pdev->dev, "failed to register miscdevice\n"); - goto free_rollup; - } - - if ((ret = find_memory_regions(rollup)) != 0) { - dev_err(&pdev->dev, "failed to parse device tree\n"); - goto free_miscdevice; - } - - alg = crypto_alloc_shash("keccak-256-generic", CRYPTO_ALG_TYPE_SHASH, 0); - if (IS_ERR(alg)) { - dev_err(&pdev->dev, "failed to create keccak-256\n"); - goto free_miscdevice; - } - - rollup->keccak = kmalloc(sizeof(rollup->keccak) + crypto_shash_descsize(alg), GFP_KERNEL); - if (!rollup->keccak) { - dev_err(&pdev->dev, "failed to allocate memory\n"); - goto free_digest; - } - rollup->keccak->tfm = alg; - - platform_set_drvdata(pdev, rollup); - rollup->pdev = pdev; - rollup->next_request_type = CARTESI_ROLLUP_INITIAL_STATE; - - mutex_init(&rollup->lock); - pr_info(MODULE_DESC ": Module loaded\n"); - return 0; - -free_digest: - crypto_free_shash(alg); -free_miscdevice: - misc_deregister(&rollup->mdev); -free_rollup: - kfree(rollup); - return ret; -} - -static int rollup_driver_remove(struct platform_device *pdev) -{ - struct rollup_device *rollup = platform_get_drvdata(pdev); - crypto_free_shash(rollup->keccak->tfm); - kfree(rollup->keccak); - misc_deregister(&rollup->mdev); - kfree(rollup); - dev_info(&pdev->dev, "unregistered\n"); - return 0; -} - -static const struct of_device_id cartesi_rollup_match[] = { - {.compatible = "ctsi-rollup",}, {}, -}; -MODULE_DEVICE_TABLE(of, cartesi_rollup_match); - -static struct platform_driver rollup_driver = { - .driver = { - .name = DEVICE_NAME, - .of_match_table = cartesi_rollup_match, - }, - .probe = rollup_driver_probe, - .remove = rollup_driver_remove, -}; - -module_platform_driver(rollup_driver); - -MODULE_DESCRIPTION(MODULE_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/cartesi/yield.c b/drivers/cartesi/yield.c deleted file mode 100644 index 12ebbb6a38f8..000000000000 --- a/drivers/cartesi/yield.c +++ /dev/null @@ -1,140 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Cartesi yield device. - * Copyright (C) 2020-2021 Cartesi Pte. Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "libyield.h" -#include - -#define DEVICE_NAME "yield" -#define FDT_YIELD_PATH "/yield" -#define MODULE_DESC "Cartesi Machine " DEVICE_NAME " device" - -static const char *available_cmds[] = { - [HTIF_YIELD_AUTOMATIC] = "automatic", - [HTIF_YIELD_MANUAL] = "manual", -}; -struct yield_device { - struct miscdevice mdev; - u64 enabled_cmds; -}; - -static struct yield_device *to_yield_device(struct file *file) -{ - struct miscdevice *dev = file->private_data; - return container_of(dev, struct yield_device, mdev); -} - -static int retrieve_enabled_cmds(struct yield_device *yield) -{ - int i, enabled_cmds_count = 0; - struct device_node *node = of_find_node_by_path(FDT_YIELD_PATH); - - for (i=0; ienabled_cmds |= (u64)p << i; - enabled_cmds_count += p; - } - return enabled_cmds_count; -} - -static long yield_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - int ret; - struct yield_device *yield; - struct yield_request req, rep; - - if ((yield = to_yield_device(file)) == NULL) - return -EBADF; - - if (cmd != IOCTL_YIELD) - return -ENOIOCTLCMD; - - if ((ret = copy_from_user(&req, (void __user*)arg, sizeof(req))) || - (ret = cartesi_yield_validate(&req)) || - (ret = yield->enabled_cmds & (1ul << req.cmd)? 0 : -EIO) || - (ret = cartesi_yield(req.cmd, req.reason, req.data, &rep)) || - (ret = copy_to_user((void __user*)arg, &rep, sizeof(rep)))) - return ret; - - return 0; -} - -static const struct file_operations yield_fileops = { - .owner = THIS_MODULE, - .unlocked_ioctl = yield_ioctl -}; - -static int yield_device_probe(struct platform_device *pdev) -{ - int ret; - struct yield_device *yield; - - yield = (struct yield_device*) kzalloc(sizeof(struct yield_device), GFP_KERNEL); - if (!yield) { - dev_err(&pdev->dev, "failed to allocate memory\n"); - return -ENOMEM; - } - - /* this should only happen on a malformed FDT in which there is an empty - * `yield` entry, that is, with no bits enabled */ - if (retrieve_enabled_cmds(yield) == 0) { - ret = -ENODEV; - dev_err(&pdev->dev, "failed to retrieve enabled yield commands\n"); - goto free_yield; - } - - yield->mdev.minor = MISC_DYNAMIC_MINOR; - yield->mdev.name = DEVICE_NAME; - yield->mdev.fops = &yield_fileops; - if ((ret = misc_register(&yield->mdev)) != 0) { - dev_err(&pdev->dev, "failed to register miscdevice\n"); - goto free_yield; - } - pr_info(MODULE_DESC ": Module loaded\n"); - return 0; - -free_yield: - kfree(yield); - return ret; -} - -static int yield_device_remove(struct platform_device *pdev) -{ - struct yield_device *yield = platform_get_drvdata(pdev); - misc_deregister(&yield->mdev); - kfree(yield); - dev_info(&pdev->dev, "unregistered\n"); - return 0; -} - -static const struct of_device_id cartesi_yield_match[] = { - {.compatible = "ctsi-yield",}, {}, -}; -MODULE_DEVICE_TABLE(of, cartesi_yield_match); - -static struct platform_driver yield_device = { - .driver = { - .name = DEVICE_NAME, - .of_match_table = cartesi_yield_match, - }, - .probe = yield_device_probe, - .remove = yield_device_remove, -}; - -module_platform_driver(yield_device); - -MODULE_DESCRIPTION(MODULE_DESC); -MODULE_LICENSE("GPL"); diff --git a/include/uapi/linux/cartesi/cmio.h b/include/uapi/linux/cartesi/cmio.h new file mode 100644 index 000000000000..ef2e8b2f7ebe --- /dev/null +++ b/include/uapi/linux/cartesi/cmio.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Cartesi cmio device. + * Copyright (C) 2023-2024 Cartesi Machine reference unit + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#ifndef _UAPI_LINUX_CARTESI_CMIO_H +#define _UAPI_LINUX_CARTESI_CMIO_H +#include +#include + +struct cmio_buffer { + __u64 data; + __u64 length; +}; + +struct cmio_setup { + struct cmio_buffer tx, rx; +}; + +/** Return a @p cmio_setup structure filled with tx and rx buffer details. Use + * these values to mmap them into the user-space. + * + * @return + * 0 on success. + * -1 on error and errno is set. */ +#define IOCTL_CMIO_SETUP _IOR (0xd3, 0, struct cmio_setup) + +/** Yield the machine execution and transfer control back to the emulator. + * + * @return + * 0 on success. + * -1 on error and errno is set. */ +#define IOCTL_CMIO_YIELD _IOWR (0xd3, 1, __u64) + +#endif diff --git a/include/uapi/linux/cartesi/rollup.h b/include/uapi/linux/cartesi/rollup.h deleted file mode 100644 index 23366ee0f5c5..000000000000 --- a/include/uapi/linux/cartesi/rollup.h +++ /dev/null @@ -1,154 +0,0 @@ -#ifndef _UAPI_LINUX_CARTESI_ROLLUP_H -#define _UAPI_LINUX_CARTESI_ROLLUP_H - -#define CARTESI_ROLLUP_ADVANCE_STATE 0 -#define CARTESI_ROLLUP_INSPECT_STATE 1 - -#define CARTESI_ROLLUP_ADDRESS_SIZE 20 - -#include -#include - -struct rollup_bytes { - __u8 *data; - __u64 length; -}; - -struct rollup_input_metadata { - __u8 msg_sender[CARTESI_ROLLUP_ADDRESS_SIZE]; - __u64 block_number; - __u64 timestamp; - __u64 epoch_index; - __u64 input_index; -}; - -struct rollup_advance_state { - struct rollup_input_metadata metadata; - struct rollup_bytes payload; -}; - -struct rollup_inspect_state { - struct rollup_bytes payload; -}; - -struct rollup_finish { - /* True if previous request should be accepted */ - /* False if previous request should be rejected */ - _Bool accept_previous_request; - - int next_request_type; /* either CARTESI_ROLLUP_ADVANCE or CARTESI_ROLLUP_INSPECT */ - int next_request_payload_length; -}; - -struct rollup_voucher { - __u8 destination[CARTESI_ROLLUP_ADDRESS_SIZE]; - struct rollup_bytes payload; - __u64 index; -}; - -struct rollup_notice { - struct rollup_bytes payload; - __u64 index; -}; - -struct rollup_report { - struct rollup_bytes payload; -}; - -struct rollup_exception { - struct rollup_bytes payload; -}; - -/* Finishes processing of current advance or inspect. - * Returns only when next advance input or inspect query is ready. - * How: - * Yields manual with rx-accepted if accept is true and yields manual with rx-rejected if accept is false. - * Once yield returns, checks the data field in fromhost to decide if next request is advance or inspect. - * Returns type and payload length of next request in struct - * on success: - * Returns 0 - * on failure: - * EFAULT in case of invalid arguments - * ERESTARTSYS in case of an internal lock error - * EIO in case of yield device error - * EOPNOTSUPP in case of an invalid next_request_type */ -#define IOCTL_ROLLUP_FINISH _IOWR(0xd3, 0, struct rollup_finish) - -/* Obtains arguments to advance state - * How: - * Reads from input metadat memory range and convert data. - * Reads from rx buffer and copy to payload - * on success: - * Returns 0 - * on failure: - * EOPNOTSUPP in case the driver is not currently processing an advance state - * EFAULT in case of invalid arguments - * ERESTARTSYS in case of an internal lock error - * EDOM in case of an integer larger than 64bits is received */ -#define IOCTL_ROLLUP_READ_ADVANCE_STATE _IOWR(0xd3, 0, struct rollup_advance_state) - -/* Obtains arguments to inspect state - * How: - * Reads from rx buffer and copy to payload - * on success: - * Returns 0 - * on failure: - * EOPNOTSUPP in case the driver is not currently processing an inspect state - * EFAULT in case of invalid arguments - * ERESTARTSYS in case of an internal lock error */ -#define IOCTL_ROLLUP_READ_INSPECT_STATE _IOWR(0xd3, 0, struct rollup_inspect_state) - -/* Outputs a new voucher. - * How: Computes the Keccak-256 hash of address+payload and then, atomically: - * - Copies the (address+be32(0x40)+be32(payload_length)+payload) to the tx buffer - * - Copies the hash to the next available slot in the voucher-hashes memory range - * - Yields automatic with tx-voucher - * - Fills in the index field with the corresponding slot from voucher-hashes - * on success: - * Returns 0 - * on failure: - * EOPNOTSUPP in case the driver is currently processing an inspect state - * EFAULT in case of invalid arguments - * ERESTARTSYS in case of an internal lock error - * EDOM in case of an integer larger than 64bits is received - * EIO in case of yield device error */ -#define IOCTL_ROLLUP_WRITE_VOUCHER _IOWR(0xd3, 1, struct rollup_voucher) - -/* Outputs a new notice. - * How: Computes the Keccak-256 hash of payload and then, atomically: - * - Copies the (be32(0x20)+be32(payload_length)+payload) to the tx buffer - * - Copies the hash to the next available slot in the notice-hashes memory range - * - Yields automatic with tx-notice - * - Fills in the index field with the corresponding slot from notice-hashes - * on success: - * Returns 0 - * on failure: - * EOPNOTSUPP in case the driver is currently processing an inspect state - * EFAULT in case of invalid arguments - * ERESTARTSYS in case of an internal lock error - * EDOM in case of an integer larger than 64bits is received - * EIO in case of yield device error */ -#define IOCTL_ROLLUP_WRITE_NOTICE _IOWR(0xd3, 2, struct rollup_notice) - -/* Outputs a new report. - * - Copies the (be32(0x20)+be32(payload_length)+payload) to the tx buffer - * - Yields automatic with tx-report - * on success: - * Returns 0 - * on failure: - * EFAULT in case of invalid arguments - * ERESTARTSYS in case of an internal lock error - * EIO in case of yield device error */ -#define IOCTL_ROLLUP_WRITE_REPORT _IOWR(0xd3, 3, struct rollup_report) - -/* Throws an exeption. - * - Copies the (be32(0x20)+be32(payload_length)+payload) to the tx buffer - * - Yields manual with tx-exception - * on success: - * Returns 0 - * on failure: - * EFAULT in case of invalid arguments - * ERESTARTSYS in case of an internal lock error - * EIO in case of yield device error */ -#define IOCTL_ROLLUP_THROW_EXCEPTION _IOWR(0xd3, 4, struct rollup_exception) -#endif diff --git a/include/uapi/linux/cartesi/yield.h b/include/uapi/linux/cartesi/yield.h deleted file mode 100644 index f17297dd9254..000000000000 --- a/include/uapi/linux/cartesi/yield.h +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * Cartesi yield device. - * Copyright (C) 2020-2021 Cartesi Pte. Ltd. - */ - -#ifndef _UAPI_LINUX_CARTESI_YIELD_H -#define _UAPI_LINUX_CARTESI_YIELD_H - -#include -#include - -struct yield_request { - __u8 dev; - __u8 cmd; - __u16 reason; - __u32 data; -}; - -#define HTIF_DEVICE_YIELD 2 - -#define HTIF_YIELD_AUTOMATIC 0 -#define HTIF_YIELD_MANUAL 1 - -#define HTIF_YIELD_REASON_PROGRESS 0 -#define HTIF_YIELD_REASON_RX_ACCEPTED 1 -#define HTIF_YIELD_REASON_RX_REJECTED 2 -#define HTIF_YIELD_REASON_TX_VOUCHER 3 -#define HTIF_YIELD_REASON_TX_NOTICE 4 -#define HTIF_YIELD_REASON_TX_REPORT 5 -#define HTIF_YIELD_REASON_TX_EXCEPTION 6 - -#define IOCTL_YIELD _IOWR(0xd1, 0, struct yield_request) - -#endif /* _UAPI_LINUX_CARTESI_YIELD_H */ diff --git a/tools/testing/selftests/drivers/cartesi/Makefile b/tools/testing/selftests/drivers/cartesi/Makefile index 5b520e5ff06b..898ba5f65d20 100644 --- a/tools/testing/selftests/drivers/cartesi/Makefile +++ b/tools/testing/selftests/drivers/cartesi/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only CFLAGS += -I../../../../../usr/include/ -TEST_GEN_PROGS := rollup_exception rollup_inspect yield +TEST_GEN_PROGS := cmio_echo cmio_open_twice top_srcdir ?=../../../../.. diff --git a/tools/testing/selftests/drivers/cartesi/cmio_echo.c b/tools/testing/selftests/drivers/cartesi/cmio_echo.c new file mode 100644 index 000000000000..5f199758de12 --- /dev/null +++ b/tools/testing/selftests/drivers/cartesi/cmio_echo.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include "../../kselftest_harness.h" + +#define DEVICE_NAME "/dev/cmio" + +FIXTURE(cmio) { + int fd; +}; +FIXTURE_SETUP(cmio) { + self->fd = open(DEVICE_NAME, O_RDWR); + ASSERT_GT(self->fd, 0) { + TH_LOG("fixture error: %s\n", strerror(errno)); + } +} +FIXTURE_TEARDOWN(cmio) { + close(self->fd); +} + +TEST_F(cmio, echo) { + const int tx_prot = PROT_READ | PROT_WRITE, + rx_prot = PROT_READ; + + struct cmio_setup setup; + + ASSERT_EQ(ioctl(self->fd, IOCTL_CMIO_SETUP, (unsigned long) &setup), 0); + uint8_t *tx = mmap((void *)setup.tx.data, setup.tx.length, tx_prot, MAP_SHARED, self->fd, 0); + uint8_t *rx = mmap((void *)setup.rx.data, setup.rx.length, rx_prot, MAP_SHARED, self->fd, 0); + + ASSERT_NE(tx, MAP_FAILED); + ASSERT_NE(rx, MAP_FAILED); + uint64_t length = + setup.rx.length < setup.tx.length? + setup.rx.length : setup.tx.length; + memcpy(tx, rx, length); +} + +TEST_HARNESS_MAIN diff --git a/tools/testing/selftests/drivers/cartesi/rollup_exception.c b/tools/testing/selftests/drivers/cartesi/rollup_exception.c deleted file mode 100644 index 2b0f57c707be..000000000000 --- a/tools/testing/selftests/drivers/cartesi/rollup_exception.c +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include -#include -#include -#include "../../kselftest_harness.h" - -#define ROLLUP_DEVICE_NAME "/dev/rollup" - -FIXTURE(rollup) { - int fd; -}; -FIXTURE_SETUP(rollup) { - self->fd = open(ROLLUP_DEVICE_NAME, O_RDWR); - ASSERT_GT(self->fd, 0) { - TH_LOG("fixture error: %s\n", strerror(self->fd)); - } -} -FIXTURE_TEARDOWN(rollup) { - close(self->fd); -} -TEST_F(rollup, exception) { - char msg[] = "exception"; - - struct rollup_exception exception = { - .payload = { - .data = msg, - .length = sizeof(msg)-1, - }, - }; - - ASSERT_EQ(ioctl(self->fd, IOCTL_ROLLUP_THROW_EXCEPTION, (unsigned long) &exception), 0); -} - -TEST_HARNESS_MAIN diff --git a/tools/testing/selftests/drivers/cartesi/rollup_inspect.c b/tools/testing/selftests/drivers/cartesi/rollup_inspect.c deleted file mode 100644 index c7bc21ca5fdf..000000000000 --- a/tools/testing/selftests/drivers/cartesi/rollup_inspect.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include -#include -#include -#include "../../kselftest_harness.h" - -#define ROLLUP_DEVICE_NAME "/dev/rollup" - -FIXTURE(rollup) { - int fd; -}; -FIXTURE_SETUP(rollup) { - self->fd = open(ROLLUP_DEVICE_NAME, O_RDWR); - ASSERT_GT(self->fd, 0) { - TH_LOG("fixture error: %s\n", strerror(self->fd)); - } -} -FIXTURE_TEARDOWN(rollup) { - close(self->fd); -} -TEST_F(rollup, voucher_and_notice_must_fail_on_inspect) { - int ret = 0; - - struct rollup_finish finish = { - .accept_previous_request = true, - }; - uint8_t msg[] = "payload"; - struct rollup_voucher voucher = { - .payload = {msg, sizeof(msg)-1}, - }; - struct rollup_notice notice = { - .payload = {msg, sizeof(msg)-1}, - }; - struct rollup_report report = { - .payload = {msg, sizeof(msg)-1}, - }; - - /* fail to emit a voucher before the first finish */ - ASSERT_EQ(ioctl(self->fd, IOCTL_ROLLUP_WRITE_VOUCHER, (unsigned long) &voucher), -1); - ASSERT_EQ(errno, EBADE); - - /* fail to emit a notice before the first finish */ - ASSERT_EQ(ioctl(self->fd, IOCTL_ROLLUP_WRITE_NOTICE, (unsigned long) ¬ice), -1); - ASSERT_EQ(errno, EBADE); - - /* fail to emit a report before the first finish */ - ASSERT_EQ(ioctl(self->fd, IOCTL_ROLLUP_WRITE_REPORT, (unsigned long) &report), -1); - ASSERT_EQ(errno, EBADE); - - ASSERT_EQ( - (ret = ioctl(self->fd, IOCTL_ROLLUP_FINISH, (unsigned long) &finish)) || - (ret = (finish.next_request_type == CARTESI_ROLLUP_INSPECT_STATE? 0 : EIO)), 0); - - /* fail to emit a voucher during a inspect */ - ASSERT_EQ(ioctl(self->fd, IOCTL_ROLLUP_WRITE_VOUCHER, (unsigned long) &voucher), -1); - ASSERT_EQ(errno, EOPNOTSUPP); - - /* fail to emit a notice during a inspect */ - ASSERT_EQ(ioctl(self->fd, IOCTL_ROLLUP_WRITE_NOTICE, (unsigned long) ¬ice), -1); - ASSERT_EQ(errno, EOPNOTSUPP); - - /* succeed to emit a report during a inspect */ - ASSERT_EQ(ioctl(self->fd, IOCTL_ROLLUP_WRITE_REPORT, (unsigned long) &report), 0); -} - -TEST_HARNESS_MAIN diff --git a/tools/testing/selftests/drivers/cartesi/yield.c b/tools/testing/selftests/drivers/cartesi/yield.c deleted file mode 100644 index cebfdafb94bd..000000000000 --- a/tools/testing/selftests/drivers/cartesi/yield.c +++ /dev/null @@ -1,43 +0,0 @@ -#include "../../kselftest_harness.h" - -#include -#include -#include - -#define YIELD_DEVICE_NAME "/dev/yield" - -FIXTURE(yield) { - int fd; -}; -FIXTURE_SETUP(yield) { - self->fd = open(YIELD_DEVICE_NAME, O_RDWR); - ASSERT_GT(self->fd, 0) { - TH_LOG("fixture error: %s\n", strerror(self->fd)); - } -} -FIXTURE_TEARDOWN(yield) { - close(self->fd); -} -TEST_F(yield, do_a_automatic_yield) { - int cmds[] = {HTIF_YIELD_AUTOMATIC, HTIF_YIELD_MANUAL}; - int reasons[] = { - HTIF_YIELD_REASON_PROGRESS, HTIF_YIELD_REASON_RX_ACCEPTED, - HTIF_YIELD_REASON_RX_REJECTED, HTIF_YIELD_REASON_TX_VOUCHER, - HTIF_YIELD_REASON_TX_NOTICE, HTIF_YIELD_REASON_TX_REPORT, - HTIF_YIELD_REASON_TX_EXCEPTION, - }; - - for (int cmd=0; cmd < ARRAY_SIZE(cmds); ++cmd) { - for (int reason=0; reason < ARRAY_SIZE(reasons); ++reason) { - struct yield_request req = { - .dev = HTIF_DEVICE_YIELD, - .cmd = cmd, - .reason = reason, - .data = (cmd * ARRAY_SIZE(reasons)) + reason, - }; - ASSERT_EQ(ioctl(self->fd, IOCTL_YIELD, (unsigned long)&req), 0); - } - } -} - -TEST_HARNESS_MAIN