This pull request contains the following changes for UML:

- Devicetree support (for testing)
 - Various cleanups and fixes: UBD, port_user, uml_mconsole
 - Maintainer update
 -----BEGIN PGP SIGNATURE-----
 
 iQJKBAABCAA0FiEEdgfidid8lnn52cLTZvlZhesYu8EFAmJFwUMWHHJpY2hhcmRA
 c2lnbWEtc3Rhci5hdAAKCRBm+VmF6xi7wQqBD/9gLyeiVp2eu1YFVir64IASgVjK
 lNdlAfUwfebtEsw65JcfY8K64910ahw6TvkjTT2A+QGeJIYaVwmw69bLXJUvQq31
 C7ZDsMHptuNiZrHDL9SoA0DfwqRdJx3tgGzDnSkhX+2T7Zs5n1nLRMBmn/NJV9Qy
 CmxG9fLH1VsU0p6RI76WST3GPLOqWa3jCeHK1vMGZNXI+eo5prHc59lkOcT7lEy7
 M4vJRaAV6pCDDYMQdDOYr1PDEeG7/h49EqdKylkOhonDyYB649rL6Lc9nRBvSts3
 NXX/qYy1Sj1AlOSR5IOon6QCyk1hap9kr85QoCtz3VMabD/yLlBovZzLOLaF+0S6
 dQWgKg806g8QYQGxN03Ph0Pb5cA6hAjr8nVmAuICJDWgmY6Oo74pEvhI8toofFzk
 NJzwa6G99xNhfggeTcGdG0ddQDT8N3enKspDPkzpN127GzU5cgvI1Z8wnZXB7JDM
 zLMCxzwehocCSrFlh9aQDFK1XJfEWuP66xEPl5cX46//IMKqsrXEOjNlCTRUmA5F
 OhU4qqb01OW3K4HPaAkBcGPZ0HhFn6JREUFyNW07dg6s73IWzf0CaNKeYJS7abln
 tdvfPg3OPNXCjHd3aCW22EzuB9R/K8BNMkva3QQZxtUa+tOjBdBd9JBJ+vHGA1MN
 7/k60wl1dt8/N9yHFg==
 =YsK8
 -----END PGP SIGNATURE-----

Merge tag 'for-linus-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml

Pull UML updates from Richard Weinberger:

 - Devicetree support (for testing)

 - Various cleanups and fixes: UBD, port_user, uml_mconsole

 - Maintainer update

* tag 'for-linus-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml:
  um: run_helper: Write error message to kernel log on exec failure on host
  um: port_user: Improve error handling when port-helper is not found
  um: port_user: Allow setting path to port-helper using UML_PORT_HELPER envvar
  um: port_user: Search for in.telnetd in PATH
  um: clang: Strip out -mno-global-merge from USER_CFLAGS
  docs: UML: Mention telnetd for port channel
  um: Remove unused timeval_to_ns() function
  um: Fix uml_mconsole stop/go
  um: Cleanup syscall_handler_t definition/cast, fix warning
  uml: net: vector: fix const issue
  um: Fix WRITE_ZEROES in the UBD Driver
  um: Migrate vector drivers to NAPI
  um: Fix order of dtb unflatten/early init
  um: fix and optimize xor select template for CONFIG64 and timetravel mode
  um: Document dtb command line option
  lib/logic_iomem: correct fallback config references
  um: Remove duplicated include in syscalls_64.c
  MAINTAINERS: Update UserModeLinux entry
This commit is contained in:
Linus Torvalds 2022-03-31 16:16:58 -07:00
Родитель a87a08e3bf 8201745795
Коммит e8b767f5e0
19 изменённых файлов: 131 добавлений и 80 удалений

Просмотреть файл

@ -1193,6 +1193,26 @@ E.g. ``os_close_file()`` is just a wrapper around ``close()``
which ensures that the userspace function close does not clash
with similarly named function(s) in the kernel part.
Using UML as a Test Platform
============================
UML is an excellent test platform for device driver development. As
with most things UML, "some user assembly may be required". It is
up to the user to build their emulation environment. UML at present
provides only the kernel infrastructure.
Part of this infrastructure is the ability to load and parse fdt
device tree blobs as used in Arm or Open Firmware platforms. These
are supplied as an optional extra argument to the kernel command
line::
dtb=filename
The device tree is loaded and parsed at boottime and is accessible by
drivers which query it. At this moment in time this facility is
intended solely for development purposes. UML's own devices do not
query the device tree.
Security Considerations
-----------------------

Просмотреть файл

@ -20539,14 +20539,15 @@ F: Documentation/admin-guide/media/zr364xx*
F: drivers/media/usb/zr364xx/
USER-MODE LINUX (UML)
M: Jeff Dike <jdike@addtoit.com>
M: Richard Weinberger <richard@nod.at>
M: Anton Ivanov <anton.ivanov@cambridgegreys.com>
M: Johannes Berg <johannes@sipsolutions.net>
L: linux-um@lists.infradead.org
S: Maintained
W: http://user-mode-linux.sourceforge.net
Q: https://patchwork.ozlabs.org/project/linux-um/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/uml/linux.git next
T: git git://git.kernel.org/pub/scm/linux/kernel/git/uml/linux.git fixes
F: Documentation/virt/uml/
F: arch/um/
F: arch/x86/um/

Просмотреть файл

@ -75,6 +75,10 @@ USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \
-D_FILE_OFFSET_BITS=64 -idirafter $(srctree)/include \
-idirafter $(objtree)/include -D__KERNEL__ -D__UM_HOST__
ifdef CONFIG_CC_IS_CLANG
USER_CFLAGS := $(patsubst -mno-global-merge,,$(USER_CFLAGS))
endif
#This will adjust *FLAGS accordingly to the platform.
include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS)

Просмотреть файл

@ -224,7 +224,7 @@ void mconsole_go(struct mc_request *req)
void mconsole_stop(struct mc_request *req)
{
deactivate_fd(req->originating_fd, MCONSOLE_IRQ);
block_signals();
os_set_fd_block(req->originating_fd, 1);
mconsole_reply(req, "stopped", 0, 0);
for (;;) {
@ -247,6 +247,7 @@ void mconsole_stop(struct mc_request *req)
}
os_set_fd_block(req->originating_fd, 0);
mconsole_reply(req, "", 0, 0);
unblock_signals();
}
static DEFINE_SPINLOCK(mc_devices_lock);

Просмотреть файл

@ -5,6 +5,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
@ -167,14 +168,29 @@ static void port_pre_exec(void *arg)
int port_connection(int fd, int *socket, int *pid_out)
{
int new, err;
char *argv[] = { "/usr/sbin/in.telnetd", "-L",
char *env;
char *argv[] = { "in.telnetd", "-L",
OS_LIB_PATH "/uml/port-helper", NULL };
struct port_pre_exec_data data;
if ((env = getenv("UML_PORT_HELPER")))
argv[2] = env;
new = accept(fd, NULL, 0);
if (new < 0)
return -errno;
err = os_access(argv[2], X_OK);
if (err < 0) {
printk(UM_KERN_ERR "port_connection : error accessing port-helper "
"executable at %s: %s\n", argv[2], strerror(-err));
if (env == NULL)
printk(UM_KERN_ERR "Set UML_PORT_HELPER environment "
"variable to path to uml-utilities port-helper "
"binary\n");
goto out_close;
}
err = os_pipe(socket, 0, 0);
if (err < 0)
goto out_close;

Просмотреть файл

@ -1526,13 +1526,19 @@ static void do_io(struct io_thread_req *req, struct io_desc *desc)
}
break;
case REQ_OP_DISCARD:
case REQ_OP_WRITE_ZEROES:
n = os_falloc_punch(req->fds[bit], off, len);
if (n) {
req->error = map_error(-n);
return;
}
break;
case REQ_OP_WRITE_ZEROES:
n = os_falloc_zeroes(req->fds[bit], off, len);
if (n) {
req->error = map_error(-n);
return;
}
break;
default:
WARN_ON_ONCE(1);
req->error = BLK_STS_NOTSUPP;

Просмотреть файл

@ -67,6 +67,7 @@ static LIST_HEAD(vector_devices);
static int driver_registered;
static void vector_eth_configure(int n, struct arglist *def);
static int vector_mmsg_rx(struct vector_private *vp, int budget);
/* Argument accessors to set variables (and/or set default values)
* mtu, buffer sizing, default headroom, etc
@ -77,7 +78,6 @@ static void vector_eth_configure(int n, struct arglist *def);
#define DEFAULT_VECTOR_SIZE 64
#define TX_SMALL_PACKET 128
#define MAX_IOV_SIZE (MAX_SKB_FRAGS + 1)
#define MAX_ITERATIONS 64
static const struct {
const char string[ETH_GSTRING_LEN];
@ -458,7 +458,6 @@ static int vector_send(struct vector_queue *qi)
vp->estats.tx_queue_running_average =
(vp->estats.tx_queue_running_average + result) >> 1;
}
netif_trans_update(qi->dev);
netif_wake_queue(qi->dev);
/* if TX is busy, break out of the send loop,
* poll write IRQ will reschedule xmit for us
@ -470,8 +469,6 @@ static int vector_send(struct vector_queue *qi)
}
}
spin_unlock(&qi->head_lock);
} else {
tasklet_schedule(&vp->tx_poll);
}
return queue_depth;
}
@ -608,7 +605,7 @@ out_fail:
/*
* We do not use the RX queue as a proper wraparound queue for now
* This is not necessary because the consumption via netif_rx()
* This is not necessary because the consumption via napi_gro_receive()
* happens in-line. While we can try using the return code of
* netif_rx() for flow control there are no drivers doing this today.
* For this RX specific use we ignore the tail/head locks and
@ -896,7 +893,7 @@ static int vector_legacy_rx(struct vector_private *vp)
skb->protocol = eth_type_trans(skb, skb->dev);
vp->dev->stats.rx_bytes += skb->len;
vp->dev->stats.rx_packets++;
netif_rx(skb);
napi_gro_receive(&vp->napi, skb);
} else {
dev_kfree_skb_irq(skb);
}
@ -955,7 +952,7 @@ drop:
* mmsg vector matched to an skb vector which we prepared earlier.
*/
static int vector_mmsg_rx(struct vector_private *vp)
static int vector_mmsg_rx(struct vector_private *vp, int budget)
{
int packet_count, i;
struct vector_queue *qi = vp->rx_queue;
@ -972,6 +969,9 @@ static int vector_mmsg_rx(struct vector_private *vp)
/* Fire the Lazy Gun - get as many packets as we can in one go. */
if (budget > qi->max_depth)
budget = qi->max_depth;
packet_count = uml_vector_recvmmsg(
vp->fds->rx_fd, qi->mmsg_vector, qi->max_depth, 0);
@ -1021,7 +1021,7 @@ static int vector_mmsg_rx(struct vector_private *vp)
*/
vp->dev->stats.rx_bytes += skb->len;
vp->dev->stats.rx_packets++;
netif_rx(skb);
napi_gro_receive(&vp->napi, skb);
} else {
/* Overlay header too short to do anything - discard.
* We can actually keep this skb and reuse it,
@ -1044,23 +1044,6 @@ static int vector_mmsg_rx(struct vector_private *vp)
return packet_count;
}
static void vector_rx(struct vector_private *vp)
{
int err;
int iter = 0;
if ((vp->options & VECTOR_RX) > 0)
while (((err = vector_mmsg_rx(vp)) > 0) && (iter < MAX_ITERATIONS))
iter++;
else
while (((err = vector_legacy_rx(vp)) > 0) && (iter < MAX_ITERATIONS))
iter++;
if ((err != 0) && net_ratelimit())
netdev_err(vp->dev, "vector_rx: error(%d)\n", err);
if (iter == MAX_ITERATIONS)
netdev_err(vp->dev, "vector_rx: device stuck, remote end may have closed the connection\n");
}
static int vector_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct vector_private *vp = netdev_priv(dev);
@ -1085,25 +1068,15 @@ static int vector_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_sent_queue(vp->dev, skb->len);
queue_depth = vector_enqueue(vp->tx_queue, skb);
/* if the device queue is full, stop the upper layers and
* flush it.
*/
if (queue_depth >= vp->tx_queue->max_depth - 1) {
vp->estats.tx_kicks++;
netif_stop_queue(dev);
vector_send(vp->tx_queue);
return NETDEV_TX_OK;
}
if (netdev_xmit_more()) {
if (queue_depth < vp->tx_queue->max_depth && netdev_xmit_more()) {
mod_timer(&vp->tl, vp->coalesce);
return NETDEV_TX_OK;
} else {
queue_depth = vector_send(vp->tx_queue);
if (queue_depth > 0)
napi_schedule(&vp->napi);
}
if (skb->len < TX_SMALL_PACKET) {
vp->estats.tx_kicks++;
vector_send(vp->tx_queue);
} else
tasklet_schedule(&vp->tx_poll);
return NETDEV_TX_OK;
}
@ -1114,7 +1087,7 @@ static irqreturn_t vector_rx_interrupt(int irq, void *dev_id)
if (!netif_running(dev))
return IRQ_NONE;
vector_rx(vp);
napi_schedule(&vp->napi);
return IRQ_HANDLED;
}
@ -1133,8 +1106,7 @@ static irqreturn_t vector_tx_interrupt(int irq, void *dev_id)
* tweaking the IRQ mask less costly
*/
if (vp->in_write_poll)
tasklet_schedule(&vp->tx_poll);
napi_schedule(&vp->napi);
return IRQ_HANDLED;
}
@ -1161,7 +1133,8 @@ static int vector_net_close(struct net_device *dev)
um_free_irq(vp->tx_irq, dev);
vp->tx_irq = 0;
}
tasklet_kill(&vp->tx_poll);
napi_disable(&vp->napi);
netif_napi_del(&vp->napi);
if (vp->fds->rx_fd > 0) {
if (vp->bpf)
uml_vector_detach_bpf(vp->fds->rx_fd, vp->bpf);
@ -1193,15 +1166,32 @@ static int vector_net_close(struct net_device *dev)
return 0;
}
/* TX tasklet */
static void vector_tx_poll(struct tasklet_struct *t)
static int vector_poll(struct napi_struct *napi, int budget)
{
struct vector_private *vp = from_tasklet(vp, t, tx_poll);
struct vector_private *vp = container_of(napi, struct vector_private, napi);
int work_done = 0;
int err;
bool tx_enqueued = false;
vp->estats.tx_kicks++;
vector_send(vp->tx_queue);
if ((vp->options & VECTOR_TX) != 0)
tx_enqueued = (vector_send(vp->tx_queue) > 0);
if ((vp->options & VECTOR_RX) > 0)
err = vector_mmsg_rx(vp, budget);
else {
err = vector_legacy_rx(vp);
if (err > 0)
err = 1;
}
if (err > 0)
work_done += err;
if (tx_enqueued || err > 0)
napi_schedule(napi);
if (work_done < budget)
napi_complete_done(napi, work_done);
return work_done;
}
static void vector_reset_tx(struct work_struct *work)
{
struct vector_private *vp =
@ -1265,6 +1255,9 @@ static int vector_net_open(struct net_device *dev)
goto out_close;
}
netif_napi_add(vp->dev, &vp->napi, vector_poll, get_depth(vp->parsed));
napi_enable(&vp->napi);
/* READ IRQ */
err = um_request_irq(
irq_rr + VECTOR_BASE_IRQ, vp->fds->rx_fd,
@ -1306,15 +1299,15 @@ static int vector_net_open(struct net_device *dev)
uml_vector_attach_bpf(vp->fds->rx_fd, vp->bpf);
netif_start_queue(dev);
vector_reset_stats(vp);
/* clear buffer - it can happen that the host side of the interface
* is full when we get here. In this case, new data is never queued,
* SIGIOs never arrive, and the net never works.
*/
vector_rx(vp);
napi_schedule(&vp->napi);
vector_reset_stats(vp);
vdevice = find_device(vp->unit);
vdevice->opened = 1;
@ -1543,15 +1536,16 @@ static const struct net_device_ops vector_netdev_ops = {
#endif
};
static void vector_timer_expire(struct timer_list *t)
{
struct vector_private *vp = from_timer(vp, t, tl);
vp->estats.tx_kicks++;
vector_send(vp->tx_queue);
napi_schedule(&vp->napi);
}
static void vector_eth_configure(
int n,
struct arglist *def
@ -1634,7 +1628,6 @@ static void vector_eth_configure(
});
dev->features = dev->hw_features = (NETIF_F_SG | NETIF_F_FRAGLIST);
tasklet_setup(&vp->tx_poll, vector_tx_poll);
INIT_WORK(&vp->reset_tx, vector_reset_tx);
timer_setup(&vp->tl, vector_timer_expire, 0);

Просмотреть файл

@ -14,6 +14,7 @@
#include <linux/ctype.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include "vector_user.h"
/* Queue structure specially adapted for multiple enqueue/dequeue
@ -72,6 +73,7 @@ struct vector_private {
struct list_head list;
spinlock_t lock;
struct net_device *dev;
struct napi_struct napi ____cacheline_aligned;
int unit;
@ -115,7 +117,6 @@ struct vector_private {
spinlock_t stats_lock;
struct tasklet_struct tx_poll;
bool rexmit_scheduled;
bool opened;
bool in_write_poll;

Просмотреть файл

@ -771,7 +771,7 @@ int uml_vector_detach_bpf(int fd, void *bpf)
printk(KERN_ERR BPF_DETACH_FAIL, prog->len, prog->filter, fd, -errno);
return err;
}
void *uml_vector_default_bpf(void *mac)
void *uml_vector_default_bpf(const void *mac)
{
struct sock_filter *bpf;
uint32_t *mac1 = (uint32_t *)(mac + 2);

Просмотреть файл

@ -97,7 +97,7 @@ extern int uml_vector_recvmmsg(
unsigned int vlen,
unsigned int flags
);
extern void *uml_vector_default_bpf(void *mac);
extern void *uml_vector_default_bpf(const void *mac);
extern void *uml_vector_user_bpf(char *filename);
extern int uml_vector_attach_bpf(int fd, void *bpf);
extern int uml_vector_detach_bpf(int fd, void *bpf);

Просмотреть файл

@ -4,8 +4,10 @@
#ifdef CONFIG_64BIT
#undef CONFIG_X86_32
#define TT_CPU_INF_XOR_DEFAULT (AVX_SELECT(&xor_block_sse_pf64))
#else
#define CONFIG_X86_32 1
#define TT_CPU_INF_XOR_DEFAULT (AVX_SELECT(&xor_block_8regs))
#endif
#include <asm/cpufeature.h>
@ -16,7 +18,7 @@
#undef XOR_SELECT_TEMPLATE
/* pick an arbitrary one - measuring isn't possible with inf-cpu */
#define XOR_SELECT_TEMPLATE(x) \
(time_travel_mode == TT_MODE_INFCPU ? &xor_block_8regs : NULL)
(time_travel_mode == TT_MODE_INFCPU ? TT_CPU_INF_XOR_DEFAULT : x))
#endif
#endif

Просмотреть файл

@ -168,6 +168,7 @@ extern unsigned os_major(unsigned long long dev);
extern unsigned os_minor(unsigned long long dev);
extern unsigned long long os_makedev(unsigned major, unsigned minor);
extern int os_falloc_punch(int fd, unsigned long long offset, int count);
extern int os_falloc_zeroes(int fd, unsigned long long offset, int count);
extern int os_eventfd(unsigned int initval, int flags);
extern int os_sendmsg_fds(int fd, const void *buf, unsigned int len,
const int *fds, unsigned int fds_num);

Просмотреть файл

@ -25,8 +25,8 @@ void uml_dtb_init(void)
return;
}
unflatten_device_tree();
early_init_fdt_scan_reserved_mem();
unflatten_device_tree();
}
static int __init uml_dtb_setup(char *line, int *add)

Просмотреть файл

@ -625,6 +625,15 @@ int os_falloc_punch(int fd, unsigned long long offset, int len)
return n;
}
int os_falloc_zeroes(int fd, unsigned long long offset, int len)
{
int n = fallocate(fd, FALLOC_FL_ZERO_RANGE|FALLOC_FL_KEEP_SIZE, offset, len);
if (n < 0)
return -errno;
return n;
}
int os_eventfd(unsigned int initval, int flags)
{
int fd = eventfd(initval, flags);

Просмотреть файл

@ -4,6 +4,7 @@
*/
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sched.h>
@ -99,6 +100,10 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
CATCH_EINTR(waitpid(pid, NULL, __WALL));
}
if (ret < 0)
printk(UM_KERN_ERR "run_helper : failed to exec %s on host: %s\n",
argv[0], strerror(-ret));
out_free2:
kfree(data.buf);
out_close:

Просмотреть файл

@ -18,12 +18,6 @@
static timer_t event_high_res_timer = 0;
static inline long long timeval_to_ns(const struct timeval *tv)
{
return ((long long) tv->tv_sec * UM_NSEC_PER_SEC) +
tv->tv_usec * UM_NSEC_PER_USEC;
}
static inline long long timespec_to_ns(const struct timespec *ts)
{
return ((long long) ts->tv_sec * UM_NSEC_PER_SEC) + ts->tv_nsec;

Просмотреть файл

@ -10,13 +10,12 @@
#include <linux/msg.h>
#include <linux/shm.h>
typedef long syscall_handler_t(void);
typedef long syscall_handler_t(long, long, long, long, long, long);
extern syscall_handler_t *sys_call_table[];
#define EXECUTE_SYSCALL(syscall, regs) \
(((long (*)(long, long, long, long, long, long)) \
(*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(&regs->regs), \
(((*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(&regs->regs), \
UPT_SYSCALL_ARG2(&regs->regs), \
UPT_SYSCALL_ARG3(&regs->regs), \
UPT_SYSCALL_ARG4(&regs->regs), \

Просмотреть файл

@ -12,7 +12,6 @@
#include <asm/prctl.h> /* XXX This should get the constants from libc */
#include <registers.h>
#include <os.h>
#include <registers.h>
long arch_prctl(struct task_struct *task, int option,
unsigned long __user *arg2)

Просмотреть файл

@ -68,7 +68,7 @@ int logic_iomem_add_region(struct resource *resource,
}
EXPORT_SYMBOL(logic_iomem_add_region);
#ifndef CONFIG_LOGIC_IOMEM_FALLBACK
#ifndef CONFIG_INDIRECT_IOMEM_FALLBACK
static void __iomem *real_ioremap(phys_addr_t offset, size_t size)
{
WARN(1, "invalid ioremap(0x%llx, 0x%zx)\n",
@ -81,7 +81,7 @@ static void real_iounmap(volatile void __iomem *addr)
WARN(1, "invalid iounmap for addr 0x%llx\n",
(unsigned long long)(uintptr_t __force)addr);
}
#endif /* CONFIG_LOGIC_IOMEM_FALLBACK */
#endif /* CONFIG_INDIRECT_IOMEM_FALLBACK */
void __iomem *ioremap(phys_addr_t offset, size_t size)
{
@ -168,7 +168,7 @@ void iounmap(volatile void __iomem *addr)
}
EXPORT_SYMBOL(iounmap);
#ifndef CONFIG_LOGIC_IOMEM_FALLBACK
#ifndef CONFIG_INDIRECT_IOMEM_FALLBACK
#define MAKE_FALLBACK(op, sz) \
static u##sz real_raw_read ## op(const volatile void __iomem *addr) \
{ \
@ -213,7 +213,7 @@ static void real_memcpy_toio(volatile void __iomem *addr, const void *buffer,
WARN(1, "Invalid memcpy_toio at address 0x%llx\n",
(unsigned long long)(uintptr_t __force)addr);
}
#endif /* CONFIG_LOGIC_IOMEM_FALLBACK */
#endif /* CONFIG_INDIRECT_IOMEM_FALLBACK */
#define MAKE_OP(op, sz) \
u##sz __raw_read ## op(const volatile void __iomem *addr) \