summaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-01-02 21:39:22 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2019-01-02 21:39:22 -0500
commit6aa293d8ff0939802a6c86cee6cd152c1b0a7a0d (patch)
treef07bcfb2e44bd8bc0a38c4b0fcc707b6ef1a7ab4 /arch/um
parent04a17edeca524b71dbb5be41a7002d247fbf34c0 (diff)
parent940b241d9050fc354f68c182e99fc3da1ff36bc0 (diff)
Merge branch 'for-linus-4.21-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml
Pull UML updates from Richard Weinberger: - DISCARD support for our block device driver - Many TLB flush optimizations - Various smaller fixes - And most important, Anton agreed to help me maintaining UML * 'for-linus-4.21-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml: um: Remove obsolete reenable_XX calls um: writev needs <sys/uio.h> Add Anton Ivanov to UML maintainers um: remove redundant generic-y um: Optimize Flush TLB for force/fork case um: Avoid marking pages with "changed protection" um: Skip TLB flushing where not needed um: Optimize TLB operations v2 um: Remove unnecessary faulted check in uaccess.c um: Add support for DISCARD in the UBD Driver um: Remove unsafe printks from the io thread um: Clean-up command processing in UML UBD driver um: Switch to block-mq constants in the UML UBD driver um: Make GCOV depend on !KCOV um: Include sys/uio.h to have writev() um: Add HAVE_DEBUG_BUGVERBOSE um: Update maintainers file entry
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/Kconfig1
-rw-r--r--arch/um/Kconfig.debug1
-rw-r--r--arch/um/drivers/chan_kern.c10
-rw-r--r--arch/um/drivers/line.c10
-rw-r--r--arch/um/drivers/mconsole_kern.c2
-rw-r--r--arch/um/drivers/net_kern.c2
-rw-r--r--arch/um/drivers/port_kern.c1
-rw-r--r--arch/um/drivers/random.c1
-rw-r--r--arch/um/drivers/ubd_kern.c231
-rw-r--r--arch/um/drivers/vector_user.c2
-rw-r--r--arch/um/include/asm/Kbuild2
-rw-r--r--arch/um/include/asm/pgtable.h9
-rw-r--r--arch/um/include/shared/irq_user.h1
-rw-r--r--arch/um/include/shared/os.h1
-rw-r--r--arch/um/kernel/irq.c6
-rw-r--r--arch/um/kernel/sigio.c1
-rw-r--r--arch/um/kernel/skas/uaccess.c23
-rw-r--r--arch/um/kernel/tlb.c115
-rw-r--r--arch/um/os-Linux/file.c10
19 files changed, 257 insertions, 172 deletions
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index a238547671d6..ec9711d068b7 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -12,6 +12,7 @@ config UML
12 select HAVE_UID16 12 select HAVE_UID16
13 select HAVE_FUTEX_CMPXCHG if FUTEX 13 select HAVE_FUTEX_CMPXCHG if FUTEX
14 select HAVE_DEBUG_KMEMLEAK 14 select HAVE_DEBUG_KMEMLEAK
15 select HAVE_DEBUG_BUGVERBOSE
15 select GENERIC_IRQ_SHOW 16 select GENERIC_IRQ_SHOW
16 select GENERIC_CPU_DEVICES 17 select GENERIC_CPU_DEVICES
17 select GENERIC_CLOCKEVENTS 18 select GENERIC_CLOCKEVENTS
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index 2014597605ea..85726eeec345 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -16,6 +16,7 @@ config GPROF
16config GCOV 16config GCOV
17 bool "Enable gcov support" 17 bool "Enable gcov support"
18 depends on DEBUG_INFO 18 depends on DEBUG_INFO
19 depends on !KCOV
19 help 20 help
20 This option allows developers to retrieve coverage data from a UML 21 This option allows developers to retrieve coverage data from a UML
21 session. 22 session.
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 05588f9466c7..a4e64edb8f38 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -211,12 +211,6 @@ void deactivate_chan(struct chan *chan, int irq)
211 deactivate_fd(chan->fd, irq); 211 deactivate_fd(chan->fd, irq);
212} 212}
213 213
214void reactivate_chan(struct chan *chan, int irq)
215{
216 if (chan && chan->enabled)
217 reactivate_fd(chan->fd, irq);
218}
219
220int write_chan(struct chan *chan, const char *buf, int len, 214int write_chan(struct chan *chan, const char *buf, int len,
221 int write_irq) 215 int write_irq)
222{ 216{
@@ -228,8 +222,6 @@ int write_chan(struct chan *chan, const char *buf, int len,
228 n = chan->ops->write(chan->fd, buf, len, chan->data); 222 n = chan->ops->write(chan->fd, buf, len, chan->data);
229 if (chan->primary) { 223 if (chan->primary) {
230 ret = n; 224 ret = n;
231 if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len)))
232 reactivate_fd(chan->fd, write_irq);
233 } 225 }
234 return ret; 226 return ret;
235} 227}
@@ -527,8 +519,6 @@ void chan_interrupt(struct line *line, int irq)
527 tty_insert_flip_char(port, c, TTY_NORMAL); 519 tty_insert_flip_char(port, c, TTY_NORMAL);
528 } while (err > 0); 520 } while (err > 0);
529 521
530 if (err == 0)
531 reactivate_fd(chan->fd, irq);
532 if (err == -EIO) { 522 if (err == -EIO) {
533 if (chan->primary) { 523 if (chan->primary) {
534 tty_port_tty_hangup(&line->port, false); 524 tty_port_tty_hangup(&line->port, false);
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 7e524efed584..e0e63931fb2b 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -235,14 +235,6 @@ void line_unthrottle(struct tty_struct *tty)
235 235
236 line->throttled = 0; 236 line->throttled = 0;
237 chan_interrupt(line, line->driver->read_irq); 237 chan_interrupt(line, line->driver->read_irq);
238
239 /*
240 * Maybe there is enough stuff pending that calling the interrupt
241 * throttles us again. In this case, line->throttled will be 1
242 * again and we shouldn't turn the interrupt back on.
243 */
244 if (!line->throttled)
245 reactivate_chan(line->chan_in, line->driver->read_irq);
246} 238}
247 239
248static irqreturn_t line_write_interrupt(int irq, void *data) 240static irqreturn_t line_write_interrupt(int irq, void *data)
@@ -667,8 +659,6 @@ static irqreturn_t winch_interrupt(int irq, void *data)
667 tty_kref_put(tty); 659 tty_kref_put(tty);
668 } 660 }
669 out: 661 out:
670 if (winch->fd != -1)
671 reactivate_fd(winch->fd, WINCH_IRQ);
672 return IRQ_HANDLED; 662 return IRQ_HANDLED;
673} 663}
674 664
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index d5f9a2d1da1b..ff3ab72fd90f 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -96,7 +96,6 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id)
96 } 96 }
97 if (!list_empty(&mc_requests)) 97 if (!list_empty(&mc_requests))
98 schedule_work(&mconsole_work); 98 schedule_work(&mconsole_work);
99 reactivate_fd(fd, MCONSOLE_IRQ);
100 return IRQ_HANDLED; 99 return IRQ_HANDLED;
101} 100}
102 101
@@ -240,7 +239,6 @@ void mconsole_stop(struct mc_request *req)
240 (*req->cmd->handler)(req); 239 (*req->cmd->handler)(req);
241 } 240 }
242 os_set_fd_block(req->originating_fd, 0); 241 os_set_fd_block(req->originating_fd, 0);
243 reactivate_fd(req->originating_fd, MCONSOLE_IRQ);
244 mconsole_reply(req, "", 0, 0); 242 mconsole_reply(req, "", 0, 0);
245} 243}
246 244
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 624cb47cc9cd..d80cfb1d9430 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -137,8 +137,6 @@ static irqreturn_t uml_net_interrupt(int irq, void *dev_id)
137 schedule_work(&lp->work); 137 schedule_work(&lp->work);
138 goto out; 138 goto out;
139 } 139 }
140 reactivate_fd(lp->fd, UM_ETH_IRQ);
141
142out: 140out:
143 spin_unlock(&lp->lock); 141 spin_unlock(&lp->lock);
144 return IRQ_HANDLED; 142 return IRQ_HANDLED;
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index 40ca5cc275e9..b0e9ff35daee 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -137,7 +137,6 @@ static void port_work_proc(struct work_struct *unused)
137 if (!port->has_connection) 137 if (!port->has_connection)
138 continue; 138 continue;
139 139
140 reactivate_fd(port->fd, ACCEPT_IRQ);
141 while (port_accept(port)) 140 while (port_accept(port))
142 ; 141 ;
143 port->has_connection = 0; 142 port->has_connection = 0;
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index 778a0e52d5a5..1d5d3057e6f1 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -73,7 +73,6 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
73 return ret ? : -EAGAIN; 73 return ret ? : -EAGAIN;
74 74
75 atomic_inc(&host_sleep_count); 75 atomic_inc(&host_sleep_count);
76 reactivate_fd(random_fd, RANDOM_IRQ);
77 add_sigio_fd(random_fd); 76 add_sigio_fd(random_fd);
78 77
79 add_wait_queue(&host_read_wait, &wait); 78 add_wait_queue(&host_read_wait, &wait);
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 28c40624bcb6..a4a41421c5e2 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -1,4 +1,5 @@
1/* 1/*
2 * Copyright (C) 2018 Cambridge Greys Ltd
2 * Copyright (C) 2015-2016 Anton Ivanov (aivanov@brocade.com) 3 * Copyright (C) 2015-2016 Anton Ivanov (aivanov@brocade.com)
3 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) 4 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
4 * Licensed under the GPL 5 * Licensed under the GPL
@@ -43,11 +44,11 @@
43#include <os.h> 44#include <os.h>
44#include "cow.h" 45#include "cow.h"
45 46
46enum ubd_req { UBD_READ, UBD_WRITE, UBD_FLUSH }; 47/* Max request size is determined by sector mask - 32K */
48#define UBD_MAX_REQUEST (8 * sizeof(long))
47 49
48struct io_thread_req { 50struct io_thread_req {
49 struct request *req; 51 struct request *req;
50 enum ubd_req op;
51 int fds[2]; 52 int fds[2];
52 unsigned long offsets[2]; 53 unsigned long offsets[2];
53 unsigned long long offset; 54 unsigned long long offset;
@@ -153,6 +154,7 @@ struct ubd {
153 struct openflags openflags; 154 struct openflags openflags;
154 unsigned shared:1; 155 unsigned shared:1;
155 unsigned no_cow:1; 156 unsigned no_cow:1;
157 unsigned no_trim:1;
156 struct cow cow; 158 struct cow cow;
157 struct platform_device pdev; 159 struct platform_device pdev;
158 struct request_queue *queue; 160 struct request_queue *queue;
@@ -176,6 +178,7 @@ struct ubd {
176 .boot_openflags = OPEN_FLAGS, \ 178 .boot_openflags = OPEN_FLAGS, \
177 .openflags = OPEN_FLAGS, \ 179 .openflags = OPEN_FLAGS, \
178 .no_cow = 0, \ 180 .no_cow = 0, \
181 .no_trim = 0, \
179 .shared = 0, \ 182 .shared = 0, \
180 .cow = DEFAULT_COW, \ 183 .cow = DEFAULT_COW, \
181 .lock = __SPIN_LOCK_UNLOCKED(ubd_devs.lock), \ 184 .lock = __SPIN_LOCK_UNLOCKED(ubd_devs.lock), \
@@ -322,7 +325,7 @@ static int ubd_setup_common(char *str, int *index_out, char **error_out)
322 *index_out = n; 325 *index_out = n;
323 326
324 err = -EINVAL; 327 err = -EINVAL;
325 for (i = 0; i < sizeof("rscd="); i++) { 328 for (i = 0; i < sizeof("rscdt="); i++) {
326 switch (*str) { 329 switch (*str) {
327 case 'r': 330 case 'r':
328 flags.w = 0; 331 flags.w = 0;
@@ -336,12 +339,15 @@ static int ubd_setup_common(char *str, int *index_out, char **error_out)
336 case 'c': 339 case 'c':
337 ubd_dev->shared = 1; 340 ubd_dev->shared = 1;
338 break; 341 break;
342 case 't':
343 ubd_dev->no_trim = 1;
344 break;
339 case '=': 345 case '=':
340 str++; 346 str++;
341 goto break_loop; 347 goto break_loop;
342 default: 348 default:
343 *error_out = "Expected '=' or flag letter " 349 *error_out = "Expected '=' or flag letter "
344 "(r, s, c, or d)"; 350 "(r, s, c, t or d)";
345 goto out; 351 goto out;
346 } 352 }
347 str++; 353 str++;
@@ -414,6 +420,7 @@ __uml_help(ubd_setup,
414" 'c' will cause the device to be treated as being shared between multiple\n" 420" 'c' will cause the device to be treated as being shared between multiple\n"
415" UMLs and file locking will be turned off - this is appropriate for a\n" 421" UMLs and file locking will be turned off - this is appropriate for a\n"
416" cluster filesystem and inappropriate at almost all other times.\n\n" 422" cluster filesystem and inappropriate at almost all other times.\n\n"
423" 't' will disable trim/discard support on the device (enabled by default).\n\n"
417); 424);
418 425
419static int udb_setup(char *str) 426static int udb_setup(char *str)
@@ -511,16 +518,21 @@ static void ubd_handler(void)
511 } 518 }
512 for (count = 0; count < n/sizeof(struct io_thread_req *); count++) { 519 for (count = 0; count < n/sizeof(struct io_thread_req *); count++) {
513 struct io_thread_req *io_req = (*irq_req_buffer)[count]; 520 struct io_thread_req *io_req = (*irq_req_buffer)[count];
514 int err = io_req->error ? BLK_STS_IOERR : BLK_STS_OK;
515
516 if (!blk_update_request(io_req->req, err, io_req->length))
517 __blk_mq_end_request(io_req->req, err);
518 521
522 if ((io_req->error == BLK_STS_NOTSUPP) && (req_op(io_req->req) == REQ_OP_DISCARD)) {
523 blk_queue_max_discard_sectors(io_req->req->q, 0);
524 blk_queue_max_write_zeroes_sectors(io_req->req->q, 0);
525 blk_queue_flag_clear(QUEUE_FLAG_DISCARD, io_req->req->q);
526 }
527 if ((io_req->error) || (io_req->buffer == NULL))
528 blk_mq_end_request(io_req->req, io_req->error);
529 else {
530 if (!blk_update_request(io_req->req, io_req->error, io_req->length))
531 __blk_mq_end_request(io_req->req, io_req->error);
532 }
519 kfree(io_req); 533 kfree(io_req);
520 } 534 }
521 } 535 }
522
523 reactivate_fd(thread_fd, UBD_IRQ);
524} 536}
525 537
526static irqreturn_t ubd_intr(int irq, void *dev) 538static irqreturn_t ubd_intr(int irq, void *dev)
@@ -789,7 +801,7 @@ static int ubd_open_dev(struct ubd *ubd_dev)
789 801
790 if((fd == -ENOENT) && create_cow){ 802 if((fd == -ENOENT) && create_cow){
791 fd = create_cow_file(ubd_dev->file, ubd_dev->cow.file, 803 fd = create_cow_file(ubd_dev->file, ubd_dev->cow.file,
792 ubd_dev->openflags, 1 << 9, PAGE_SIZE, 804 ubd_dev->openflags, SECTOR_SIZE, PAGE_SIZE,
793 &ubd_dev->cow.bitmap_offset, 805 &ubd_dev->cow.bitmap_offset,
794 &ubd_dev->cow.bitmap_len, 806 &ubd_dev->cow.bitmap_len,
795 &ubd_dev->cow.data_offset); 807 &ubd_dev->cow.data_offset);
@@ -830,6 +842,14 @@ static int ubd_open_dev(struct ubd *ubd_dev)
830 if(err < 0) goto error; 842 if(err < 0) goto error;
831 ubd_dev->cow.fd = err; 843 ubd_dev->cow.fd = err;
832 } 844 }
845 if (ubd_dev->no_trim == 0) {
846 ubd_dev->queue->limits.discard_granularity = SECTOR_SIZE;
847 ubd_dev->queue->limits.discard_alignment = SECTOR_SIZE;
848 blk_queue_max_discard_sectors(ubd_dev->queue, UBD_MAX_REQUEST);
849 blk_queue_max_write_zeroes_sectors(ubd_dev->queue, UBD_MAX_REQUEST);
850 blk_queue_flag_set(QUEUE_FLAG_DISCARD, ubd_dev->queue);
851 }
852 blk_queue_flag_set(QUEUE_FLAG_NONROT, ubd_dev->queue);
833 return 0; 853 return 0;
834 error: 854 error:
835 os_close_file(ubd_dev->fd); 855 os_close_file(ubd_dev->fd);
@@ -882,7 +902,7 @@ static int ubd_disk_register(int major, u64 size, int unit,
882 return 0; 902 return 0;
883} 903}
884 904
885#define ROUND_BLOCK(n) ((n + ((1 << 9) - 1)) & (-1 << 9)) 905#define ROUND_BLOCK(n) ((n + (SECTOR_SIZE - 1)) & (-SECTOR_SIZE))
886 906
887static const struct blk_mq_ops ubd_mq_ops = { 907static const struct blk_mq_ops ubd_mq_ops = {
888 .queue_rq = ubd_queue_rq, 908 .queue_rq = ubd_queue_rq,
@@ -1234,10 +1254,10 @@ static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
1234 __u64 bitmap_offset, unsigned long *bitmap_words, 1254 __u64 bitmap_offset, unsigned long *bitmap_words,
1235 __u64 bitmap_len) 1255 __u64 bitmap_len)
1236{ 1256{
1237 __u64 sector = io_offset >> 9; 1257 __u64 sector = io_offset >> SECTOR_SHIFT;
1238 int i, update_bitmap = 0; 1258 int i, update_bitmap = 0;
1239 1259
1240 for(i = 0; i < length >> 9; i++){ 1260 for (i = 0; i < length >> SECTOR_SHIFT; i++) {
1241 if(cow_mask != NULL) 1261 if(cow_mask != NULL)
1242 ubd_set_bit(i, (unsigned char *) cow_mask); 1262 ubd_set_bit(i, (unsigned char *) cow_mask);
1243 if(ubd_test_bit(sector + i, (unsigned char *) bitmap)) 1263 if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
@@ -1271,14 +1291,14 @@ static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
1271static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, 1291static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
1272 __u64 bitmap_offset, __u64 bitmap_len) 1292 __u64 bitmap_offset, __u64 bitmap_len)
1273{ 1293{
1274 __u64 sector = req->offset >> 9; 1294 __u64 sector = req->offset >> SECTOR_SHIFT;
1275 int i; 1295 int i;
1276 1296
1277 if(req->length > (sizeof(req->sector_mask) * 8) << 9) 1297 if (req->length > (sizeof(req->sector_mask) * 8) << SECTOR_SHIFT)
1278 panic("Operation too long"); 1298 panic("Operation too long");
1279 1299
1280 if(req->op == UBD_READ) { 1300 if (req_op(req->req) == REQ_OP_READ) {
1281 for(i = 0; i < req->length >> 9; i++){ 1301 for (i = 0; i < req->length >> SECTOR_SHIFT; i++) {
1282 if(ubd_test_bit(sector + i, (unsigned char *) bitmap)) 1302 if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
1283 ubd_set_bit(i, (unsigned char *) 1303 ubd_set_bit(i, (unsigned char *)
1284 &req->sector_mask); 1304 &req->sector_mask);
@@ -1307,68 +1327,86 @@ static int ubd_queue_one_vec(struct blk_mq_hw_ctx *hctx, struct request *req,
1307 io_req->fds[0] = dev->fd; 1327 io_req->fds[0] = dev->fd;
1308 io_req->error = 0; 1328 io_req->error = 0;
1309 1329
1310 if (req_op(req) == REQ_OP_FLUSH) { 1330 if (bvec != NULL) {
1311 io_req->op = UBD_FLUSH;
1312 } else {
1313 io_req->fds[1] = dev->fd;
1314 io_req->cow_offset = -1;
1315 io_req->offset = off;
1316 io_req->length = bvec->bv_len;
1317 io_req->sector_mask = 0;
1318 io_req->op = rq_data_dir(req) == READ ? UBD_READ : UBD_WRITE;
1319 io_req->offsets[0] = 0;
1320 io_req->offsets[1] = dev->cow.data_offset;
1321 io_req->buffer = page_address(bvec->bv_page) + bvec->bv_offset; 1331 io_req->buffer = page_address(bvec->bv_page) + bvec->bv_offset;
1322 io_req->sectorsize = 1 << 9; 1332 io_req->length = bvec->bv_len;
1323 1333 } else {
1324 if (dev->cow.file) { 1334 io_req->buffer = NULL;
1325 cowify_req(io_req, dev->cow.bitmap, 1335 io_req->length = blk_rq_bytes(req);
1326 dev->cow.bitmap_offset, dev->cow.bitmap_len);
1327 }
1328 } 1336 }
1329 1337
1338 io_req->sectorsize = SECTOR_SIZE;
1339 io_req->fds[1] = dev->fd;
1340 io_req->cow_offset = -1;
1341 io_req->offset = off;
1342 io_req->sector_mask = 0;
1343 io_req->offsets[0] = 0;
1344 io_req->offsets[1] = dev->cow.data_offset;
1345
1346 if (dev->cow.file)
1347 cowify_req(io_req, dev->cow.bitmap,
1348 dev->cow.bitmap_offset, dev->cow.bitmap_len);
1349
1330 ret = os_write_file(thread_fd, &io_req, sizeof(io_req)); 1350 ret = os_write_file(thread_fd, &io_req, sizeof(io_req));
1331 if (ret != sizeof(io_req)) { 1351 if (ret != sizeof(io_req)) {
1332 if (ret != -EAGAIN) 1352 if (ret != -EAGAIN)
1333 pr_err("write to io thread failed: %d\n", -ret); 1353 pr_err("write to io thread failed: %d\n", -ret);
1334 kfree(io_req); 1354 kfree(io_req);
1335 } 1355 }
1336
1337 return ret; 1356 return ret;
1338} 1357}
1339 1358
1359static int queue_rw_req(struct blk_mq_hw_ctx *hctx, struct request *req)
1360{
1361 struct req_iterator iter;
1362 struct bio_vec bvec;
1363 int ret;
1364 u64 off = (u64)blk_rq_pos(req) << SECTOR_SHIFT;
1365
1366 rq_for_each_segment(bvec, req, iter) {
1367 ret = ubd_queue_one_vec(hctx, req, off, &bvec);
1368 if (ret < 0)
1369 return ret;
1370 off += bvec.bv_len;
1371 }
1372 return 0;
1373}
1374
1340static blk_status_t ubd_queue_rq(struct blk_mq_hw_ctx *hctx, 1375static blk_status_t ubd_queue_rq(struct blk_mq_hw_ctx *hctx,
1341 const struct blk_mq_queue_data *bd) 1376 const struct blk_mq_queue_data *bd)
1342{ 1377{
1343 struct ubd *ubd_dev = hctx->queue->queuedata; 1378 struct ubd *ubd_dev = hctx->queue->queuedata;
1344 struct request *req = bd->rq; 1379 struct request *req = bd->rq;
1345 int ret = 0; 1380 int ret = 0, res = BLK_STS_OK;
1346 1381
1347 blk_mq_start_request(req); 1382 blk_mq_start_request(req);
1348 1383
1349 spin_lock_irq(&ubd_dev->lock); 1384 spin_lock_irq(&ubd_dev->lock);
1350 1385
1351 if (req_op(req) == REQ_OP_FLUSH) { 1386 switch (req_op(req)) {
1387 /* operations with no lentgth/offset arguments */
1388 case REQ_OP_FLUSH:
1352 ret = ubd_queue_one_vec(hctx, req, 0, NULL); 1389 ret = ubd_queue_one_vec(hctx, req, 0, NULL);
1353 } else { 1390 break;
1354 struct req_iterator iter; 1391 case REQ_OP_READ:
1355 struct bio_vec bvec; 1392 case REQ_OP_WRITE:
1356 u64 off = (u64)blk_rq_pos(req) << 9; 1393 ret = queue_rw_req(hctx, req);
1357 1394 break;
1358 rq_for_each_segment(bvec, req, iter) { 1395 case REQ_OP_DISCARD:
1359 ret = ubd_queue_one_vec(hctx, req, off, &bvec); 1396 case REQ_OP_WRITE_ZEROES:
1360 if (ret < 0) 1397 ret = ubd_queue_one_vec(hctx, req, (u64)blk_rq_pos(req) << 9, NULL);
1361 goto out; 1398 break;
1362 off += bvec.bv_len; 1399 default:
1363 } 1400 WARN_ON_ONCE(1);
1401 res = BLK_STS_NOTSUPP;
1364 } 1402 }
1365out: 1403
1366 spin_unlock_irq(&ubd_dev->lock); 1404 spin_unlock_irq(&ubd_dev->lock);
1367 1405
1368 if (ret < 0) 1406 if (ret < 0)
1369 blk_mq_requeue_request(req, true); 1407 blk_mq_requeue_request(req, true);
1370 1408
1371 return BLK_STS_OK; 1409 return res;
1372} 1410}
1373 1411
1374static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo) 1412static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
@@ -1413,39 +1451,60 @@ static int ubd_ioctl(struct block_device *bdev, fmode_t mode,
1413 return -EINVAL; 1451 return -EINVAL;
1414} 1452}
1415 1453
1454static int map_error(int error_code)
1455{
1456 switch (error_code) {
1457 case 0:
1458 return BLK_STS_OK;
1459 case ENOSYS:
1460 case EOPNOTSUPP:
1461 return BLK_STS_NOTSUPP;
1462 case ENOSPC:
1463 return BLK_STS_NOSPC;
1464 }
1465 return BLK_STS_IOERR;
1466}
1467
1468/*
1469 * Everything from here onwards *IS NOT PART OF THE KERNEL*
1470 *
1471 * The following functions are part of UML hypervisor code.
1472 * All functions from here onwards are executed as a helper
1473 * thread and are not allowed to execute any kernel functions.
1474 *
1475 * Any communication must occur strictly via shared memory and IPC.
1476 *
1477 * Do not add printks, locks, kernel memory operations, etc - it
1478 * will result in unpredictable behaviour and/or crashes.
1479 */
1480
1416static int update_bitmap(struct io_thread_req *req) 1481static int update_bitmap(struct io_thread_req *req)
1417{ 1482{
1418 int n; 1483 int n;
1419 1484
1420 if(req->cow_offset == -1) 1485 if(req->cow_offset == -1)
1421 return 0; 1486 return map_error(0);
1422 1487
1423 n = os_pwrite_file(req->fds[1], &req->bitmap_words, 1488 n = os_pwrite_file(req->fds[1], &req->bitmap_words,
1424 sizeof(req->bitmap_words), req->cow_offset); 1489 sizeof(req->bitmap_words), req->cow_offset);
1425 if(n != sizeof(req->bitmap_words)){ 1490 if (n != sizeof(req->bitmap_words))
1426 printk("do_io - bitmap update failed, err = %d fd = %d\n", -n, 1491 return map_error(-n);
1427 req->fds[1]);
1428 return 1;
1429 }
1430 1492
1431 return 0; 1493 return map_error(0);
1432} 1494}
1433 1495
1434static void do_io(struct io_thread_req *req) 1496static void do_io(struct io_thread_req *req)
1435{ 1497{
1436 char *buf; 1498 char *buf = NULL;
1437 unsigned long len; 1499 unsigned long len;
1438 int n, nsectors, start, end, bit; 1500 int n, nsectors, start, end, bit;
1439 __u64 off; 1501 __u64 off;
1440 1502
1441 if (req->op == UBD_FLUSH) { 1503 /* FLUSH is really a special case, we cannot "case" it with others */
1504
1505 if (req_op(req->req) == REQ_OP_FLUSH) {
1442 /* fds[0] is always either the rw image or our cow file */ 1506 /* fds[0] is always either the rw image or our cow file */
1443 n = os_sync_file(req->fds[0]); 1507 req->error = map_error(-os_sync_file(req->fds[0]));
1444 if (n != 0) {
1445 printk("do_io - sync failed err = %d "
1446 "fd = %d\n", -n, req->fds[0]);
1447 req->error = 1;
1448 }
1449 return; 1508 return;
1450 } 1509 }
1451 1510
@@ -1462,30 +1521,42 @@ static void do_io(struct io_thread_req *req)
1462 off = req->offset + req->offsets[bit] + 1521 off = req->offset + req->offsets[bit] +
1463 start * req->sectorsize; 1522 start * req->sectorsize;
1464 len = (end - start) * req->sectorsize; 1523 len = (end - start) * req->sectorsize;
1465 buf = &req->buffer[start * req->sectorsize]; 1524 if (req->buffer != NULL)
1525 buf = &req->buffer[start * req->sectorsize];
1466 1526
1467 if(req->op == UBD_READ){ 1527 switch (req_op(req->req)) {
1528 case REQ_OP_READ:
1468 n = 0; 1529 n = 0;
1469 do { 1530 do {
1470 buf = &buf[n]; 1531 buf = &buf[n];
1471 len -= n; 1532 len -= n;
1472 n = os_pread_file(req->fds[bit], buf, len, off); 1533 n = os_pread_file(req->fds[bit], buf, len, off);
1473 if (n < 0) { 1534 if (n < 0) {
1474 printk("do_io - read failed, err = %d " 1535 req->error = map_error(-n);
1475 "fd = %d\n", -n, req->fds[bit]);
1476 req->error = 1;
1477 return; 1536 return;
1478 } 1537 }
1479 } while((n < len) && (n != 0)); 1538 } while((n < len) && (n != 0));
1480 if (n < len) memset(&buf[n], 0, len - n); 1539 if (n < len) memset(&buf[n], 0, len - n);
1481 } else { 1540 break;
1541 case REQ_OP_WRITE:
1482 n = os_pwrite_file(req->fds[bit], buf, len, off); 1542 n = os_pwrite_file(req->fds[bit], buf, len, off);
1483 if(n != len){ 1543 if(n != len){
1484 printk("do_io - write failed err = %d " 1544 req->error = map_error(-n);
1485 "fd = %d\n", -n, req->fds[bit]); 1545 return;
1486 req->error = 1; 1546 }
1547 break;
1548 case REQ_OP_DISCARD:
1549 case REQ_OP_WRITE_ZEROES:
1550 n = os_falloc_punch(req->fds[bit], off, len);
1551 if (n) {
1552 req->error = map_error(-n);
1487 return; 1553 return;
1488 } 1554 }
1555 break;
1556 default:
1557 WARN_ON_ONCE(1);
1558 req->error = BLK_STS_NOTSUPP;
1559 return;
1489 } 1560 }
1490 1561
1491 start = end; 1562 start = end;
@@ -1520,11 +1591,6 @@ int io_thread(void *arg)
1520 if (n == -EAGAIN) { 1591 if (n == -EAGAIN) {
1521 ubd_read_poll(-1); 1592 ubd_read_poll(-1);
1522 continue; 1593 continue;
1523 } else {
1524 printk("io_thread - read failed, fd = %d, "
1525 "err = %d,"
1526 "reminder = %d\n",
1527 kernel_fd, -n, io_remainder_size);
1528 } 1594 }
1529 } 1595 }
1530 1596
@@ -1539,11 +1605,6 @@ int io_thread(void *arg)
1539 res = os_write_file(kernel_fd, ((char *) io_req_buffer) + written, n); 1605 res = os_write_file(kernel_fd, ((char *) io_req_buffer) + written, n);
1540 if (res >= 0) { 1606 if (res >= 0) {
1541 written += res; 1607 written += res;
1542 } else {
1543 if (res != -EAGAIN) {
1544 printk("io_thread - write failed, fd = %d, "
1545 "err = %d\n", kernel_fd, -n);
1546 }
1547 } 1608 }
1548 if (written < n) { 1609 if (written < n) {
1549 ubd_write_poll(-1); 1610 ubd_write_poll(-1);
diff --git a/arch/um/drivers/vector_user.c b/arch/um/drivers/vector_user.c
index 3d8cdbdb4e66..d2c17dd74620 100644
--- a/arch/um/drivers/vector_user.c
+++ b/arch/um/drivers/vector_user.c
@@ -25,11 +25,13 @@
25#include <linux/if_packet.h> 25#include <linux/if_packet.h>
26#include <sys/socket.h> 26#include <sys/socket.h>
27#include <sys/wait.h> 27#include <sys/wait.h>
28#include <sys/uio.h>
28#include <linux/virtio_net.h> 29#include <linux/virtio_net.h>
29#include <netdb.h> 30#include <netdb.h>
30#include <stdlib.h> 31#include <stdlib.h>
31#include <os.h> 32#include <os.h>
32#include <um_malloc.h> 33#include <um_malloc.h>
34#include <sys/uio.h>
33#include "vector_user.h" 35#include "vector_user.h"
34 36
35#define ID_GRE 0 37#define ID_GRE 0
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index b10dde6cb793..00bcbe2326d9 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -10,9 +10,7 @@ generic-y += exec.h
10generic-y += extable.h 10generic-y += extable.h
11generic-y += ftrace.h 11generic-y += ftrace.h
12generic-y += futex.h 12generic-y += futex.h
13generic-y += hardirq.h
14generic-y += hw_irq.h 13generic-y += hw_irq.h
15generic-y += io.h
16generic-y += irq_regs.h 14generic-y += irq_regs.h
17generic-y += irq_work.h 15generic-y += irq_work.h
18generic-y += kdebug.h 16generic-y += kdebug.h
diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h
index 7485398d0737..9c04562310b3 100644
--- a/arch/um/include/asm/pgtable.h
+++ b/arch/um/include/asm/pgtable.h
@@ -197,12 +197,17 @@ static inline pte_t pte_mkold(pte_t pte)
197 197
198static inline pte_t pte_wrprotect(pte_t pte) 198static inline pte_t pte_wrprotect(pte_t pte)
199{ 199{
200 pte_clear_bits(pte, _PAGE_RW); 200 if (likely(pte_get_bits(pte, _PAGE_RW)))
201 pte_clear_bits(pte, _PAGE_RW);
202 else
203 return pte;
201 return(pte_mknewprot(pte)); 204 return(pte_mknewprot(pte));
202} 205}
203 206
204static inline pte_t pte_mkread(pte_t pte) 207static inline pte_t pte_mkread(pte_t pte)
205{ 208{
209 if (unlikely(pte_get_bits(pte, _PAGE_USER)))
210 return pte;
206 pte_set_bits(pte, _PAGE_USER); 211 pte_set_bits(pte, _PAGE_USER);
207 return(pte_mknewprot(pte)); 212 return(pte_mknewprot(pte));
208} 213}
@@ -221,6 +226,8 @@ static inline pte_t pte_mkyoung(pte_t pte)
221 226
222static inline pte_t pte_mkwrite(pte_t pte) 227static inline pte_t pte_mkwrite(pte_t pte)
223{ 228{
229 if (unlikely(pte_get_bits(pte, _PAGE_RW)))
230 return pte;
224 pte_set_bits(pte, _PAGE_RW); 231 pte_set_bits(pte, _PAGE_RW);
225 return(pte_mknewprot(pte)); 232 return(pte_mknewprot(pte));
226} 233}
diff --git a/arch/um/include/shared/irq_user.h b/arch/um/include/shared/irq_user.h
index a7a6120f19d5..e7242a0ae489 100644
--- a/arch/um/include/shared/irq_user.h
+++ b/arch/um/include/shared/irq_user.h
@@ -31,7 +31,6 @@ struct irq_fd {
31struct siginfo; 31struct siginfo;
32extern void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); 32extern void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs);
33extern void free_irq_by_fd(int fd); 33extern void free_irq_by_fd(int fd);
34extern void reactivate_fd(int fd, int irqnum);
35extern void deactivate_fd(int fd, int irqnum); 34extern void deactivate_fd(int fd, int irqnum);
36extern int deactivate_all_fds(void); 35extern int deactivate_all_fds(void);
37extern int activate_ipi(int fd, int pid); 36extern int activate_ipi(int fd, int pid);
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h
index 048ae37eb5aa..ebf23012a59b 100644
--- a/arch/um/include/shared/os.h
+++ b/arch/um/include/shared/os.h
@@ -175,6 +175,7 @@ extern int os_fchange_dir(int fd);
175extern unsigned os_major(unsigned long long dev); 175extern unsigned os_major(unsigned long long dev);
176extern unsigned os_minor(unsigned long long dev); 176extern unsigned os_minor(unsigned long long dev);
177extern unsigned long long os_makedev(unsigned major, unsigned minor); 177extern unsigned long long os_makedev(unsigned major, unsigned minor);
178extern int os_falloc_punch(int fd, unsigned long long offset, int count);
178 179
179/* start_up.c */ 180/* start_up.c */
180extern void os_early_checks(void); 181extern void os_early_checks(void);
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 8360fa3f676d..f4874b7ec503 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -350,11 +350,6 @@ static void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
350} 350}
351 351
352 352
353void reactivate_fd(int fd, int irqnum)
354{
355 /** NOP - we do auto-EOI now **/
356}
357
358void deactivate_fd(int fd, int irqnum) 353void deactivate_fd(int fd, int irqnum)
359{ 354{
360 struct irq_entry *to_free; 355 struct irq_entry *to_free;
@@ -449,7 +444,6 @@ int um_request_irq(unsigned int irq, int fd, int type,
449} 444}
450 445
451EXPORT_SYMBOL(um_request_irq); 446EXPORT_SYMBOL(um_request_irq);
452EXPORT_SYMBOL(reactivate_fd);
453 447
454/* 448/*
455 * irq_chip must define at least enable/disable and ack when 449 * irq_chip must define at least enable/disable and ack when
diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c
index b5e0cbb34382..3fb6a4041ed6 100644
--- a/arch/um/kernel/sigio.c
+++ b/arch/um/kernel/sigio.c
@@ -16,7 +16,6 @@ static irqreturn_t sigio_interrupt(int irq, void *data)
16 char c; 16 char c;
17 17
18 os_read_file(sigio_irq_fd, &c, sizeof(c)); 18 os_read_file(sigio_irq_fd, &c, sizeof(c));
19 reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ);
20 return IRQ_HANDLED; 19 return IRQ_HANDLED;
21} 20}
22 21
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index d450797a3a7c..7f06fdbc7ee1 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -62,27 +62,28 @@ static int do_op_one_page(unsigned long addr, int len, int is_write,
62 jmp_buf buf; 62 jmp_buf buf;
63 struct page *page; 63 struct page *page;
64 pte_t *pte; 64 pte_t *pte;
65 int n, faulted; 65 int n;
66 66
67 pte = maybe_map(addr, is_write); 67 pte = maybe_map(addr, is_write);
68 if (pte == NULL) 68 if (pte == NULL)
69 return -1; 69 return -1;
70 70
71 page = pte_page(*pte); 71 page = pte_page(*pte);
72#ifdef CONFIG_64BIT
73 pagefault_disable();
74 addr = (unsigned long) page_address(page) +
75 (addr & ~PAGE_MASK);
76#else
72 addr = (unsigned long) kmap_atomic(page) + 77 addr = (unsigned long) kmap_atomic(page) +
73 (addr & ~PAGE_MASK); 78 (addr & ~PAGE_MASK);
79#endif
80 n = (*op)(addr, len, arg);
74 81
75 current->thread.fault_catcher = &buf; 82#ifdef CONFIG_64BIT
76 83 pagefault_enable();
77 faulted = UML_SETJMP(&buf); 84#else
78 if (faulted == 0)
79 n = (*op)(addr, len, arg);
80 else
81 n = -1;
82
83 current->thread.fault_catcher = NULL;
84
85 kunmap_atomic((void *)addr); 85 kunmap_atomic((void *)addr);
86#endif
86 87
87 return n; 88 return n;
88} 89}
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index 37508b190106..8347161c2ae0 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -37,17 +37,19 @@ struct host_vm_change {
37 } mprotect; 37 } mprotect;
38 } u; 38 } u;
39 } ops[1]; 39 } ops[1];
40 int userspace;
40 int index; 41 int index;
41 struct mm_id *id; 42 struct mm_struct *mm;
42 void *data; 43 void *data;
43 int force; 44 int force;
44}; 45};
45 46
46#define INIT_HVC(mm, force) \ 47#define INIT_HVC(mm, force, userspace) \
47 ((struct host_vm_change) \ 48 ((struct host_vm_change) \
48 { .ops = { { .type = NONE } }, \ 49 { .ops = { { .type = NONE } }, \
49 .id = &mm->context.id, \ 50 .mm = mm, \
50 .data = NULL, \ 51 .data = NULL, \
52 .userspace = userspace, \
51 .index = 0, \ 53 .index = 0, \
52 .force = force }) 54 .force = force })
53 55
@@ -68,18 +70,40 @@ static int do_ops(struct host_vm_change *hvc, int end,
68 op = &hvc->ops[i]; 70 op = &hvc->ops[i];
69 switch (op->type) { 71 switch (op->type) {
70 case MMAP: 72 case MMAP:
71 ret = map(hvc->id, op->u.mmap.addr, op->u.mmap.len, 73 if (hvc->userspace)
72 op->u.mmap.prot, op->u.mmap.fd, 74 ret = map(&hvc->mm->context.id, op->u.mmap.addr,
73 op->u.mmap.offset, finished, &hvc->data); 75 op->u.mmap.len, op->u.mmap.prot,
76 op->u.mmap.fd,
77 op->u.mmap.offset, finished,
78 &hvc->data);
79 else
80 map_memory(op->u.mmap.addr, op->u.mmap.offset,
81 op->u.mmap.len, 1, 1, 1);
74 break; 82 break;
75 case MUNMAP: 83 case MUNMAP:
76 ret = unmap(hvc->id, op->u.munmap.addr, 84 if (hvc->userspace)
77 op->u.munmap.len, finished, &hvc->data); 85 ret = unmap(&hvc->mm->context.id,
86 op->u.munmap.addr,
87 op->u.munmap.len, finished,
88 &hvc->data);
89 else
90 ret = os_unmap_memory(
91 (void *) op->u.munmap.addr,
92 op->u.munmap.len);
93
78 break; 94 break;
79 case MPROTECT: 95 case MPROTECT:
80 ret = protect(hvc->id, op->u.mprotect.addr, 96 if (hvc->userspace)
81 op->u.mprotect.len, op->u.mprotect.prot, 97 ret = protect(&hvc->mm->context.id,
82 finished, &hvc->data); 98 op->u.mprotect.addr,
99 op->u.mprotect.len,
100 op->u.mprotect.prot,
101 finished, &hvc->data);
102 else
103 ret = os_protect_memory(
104 (void *) op->u.mprotect.addr,
105 op->u.mprotect.len,
106 1, 1, 1);
83 break; 107 break;
84 default: 108 default:
85 printk(KERN_ERR "Unknown op type %d in do_ops\n", 109 printk(KERN_ERR "Unknown op type %d in do_ops\n",
@@ -100,9 +124,12 @@ static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
100{ 124{
101 __u64 offset; 125 __u64 offset;
102 struct host_vm_op *last; 126 struct host_vm_op *last;
103 int fd, ret = 0; 127 int fd = -1, ret = 0;
104 128
105 fd = phys_mapping(phys, &offset); 129 if (hvc->userspace)
130 fd = phys_mapping(phys, &offset);
131 else
132 offset = phys;
106 if (hvc->index != 0) { 133 if (hvc->index != 0) {
107 last = &hvc->ops[hvc->index - 1]; 134 last = &hvc->ops[hvc->index - 1];
108 if ((last->type == MMAP) && 135 if ((last->type == MMAP) &&
@@ -215,10 +242,11 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
215 prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | 242 prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
216 (x ? UM_PROT_EXEC : 0)); 243 (x ? UM_PROT_EXEC : 0));
217 if (hvc->force || pte_newpage(*pte)) { 244 if (hvc->force || pte_newpage(*pte)) {
218 if (pte_present(*pte)) 245 if (pte_present(*pte)) {
219 ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK, 246 if (pte_newpage(*pte))
220 PAGE_SIZE, prot, hvc); 247 ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK,
221 else 248 PAGE_SIZE, prot, hvc);
249 } else
222 ret = add_munmap(addr, PAGE_SIZE, hvc); 250 ret = add_munmap(addr, PAGE_SIZE, hvc);
223 } else if (pte_newprot(*pte)) 251 } else if (pte_newprot(*pte))
224 ret = add_mprotect(addr, PAGE_SIZE, prot, hvc); 252 ret = add_mprotect(addr, PAGE_SIZE, prot, hvc);
@@ -277,9 +305,9 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
277 pgd_t *pgd; 305 pgd_t *pgd;
278 struct host_vm_change hvc; 306 struct host_vm_change hvc;
279 unsigned long addr = start_addr, next; 307 unsigned long addr = start_addr, next;
280 int ret = 0; 308 int ret = 0, userspace = 1;
281 309
282 hvc = INIT_HVC(mm, force); 310 hvc = INIT_HVC(mm, force, userspace);
283 pgd = pgd_offset(mm, addr); 311 pgd = pgd_offset(mm, addr);
284 do { 312 do {
285 next = pgd_addr_end(addr, end_addr); 313 next = pgd_addr_end(addr, end_addr);
@@ -314,9 +342,11 @@ static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
314 pmd_t *pmd; 342 pmd_t *pmd;
315 pte_t *pte; 343 pte_t *pte;
316 unsigned long addr, last; 344 unsigned long addr, last;
317 int updated = 0, err; 345 int updated = 0, err = 0, force = 0, userspace = 0;
346 struct host_vm_change hvc;
318 347
319 mm = &init_mm; 348 mm = &init_mm;
349 hvc = INIT_HVC(mm, force, userspace);
320 for (addr = start; addr < end;) { 350 for (addr = start; addr < end;) {
321 pgd = pgd_offset(mm, addr); 351 pgd = pgd_offset(mm, addr);
322 if (!pgd_present(*pgd)) { 352 if (!pgd_present(*pgd)) {
@@ -325,8 +355,7 @@ static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
325 last = end; 355 last = end;
326 if (pgd_newpage(*pgd)) { 356 if (pgd_newpage(*pgd)) {
327 updated = 1; 357 updated = 1;
328 err = os_unmap_memory((void *) addr, 358 err = add_munmap(addr, last - addr, &hvc);
329 last - addr);
330 if (err < 0) 359 if (err < 0)
331 panic("munmap failed, errno = %d\n", 360 panic("munmap failed, errno = %d\n",
332 -err); 361 -err);
@@ -342,8 +371,7 @@ static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
342 last = end; 371 last = end;
343 if (pud_newpage(*pud)) { 372 if (pud_newpage(*pud)) {
344 updated = 1; 373 updated = 1;
345 err = os_unmap_memory((void *) addr, 374 err = add_munmap(addr, last - addr, &hvc);
346 last - addr);
347 if (err < 0) 375 if (err < 0)
348 panic("munmap failed, errno = %d\n", 376 panic("munmap failed, errno = %d\n",
349 -err); 377 -err);
@@ -359,8 +387,7 @@ static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
359 last = end; 387 last = end;
360 if (pmd_newpage(*pmd)) { 388 if (pmd_newpage(*pmd)) {
361 updated = 1; 389 updated = 1;
362 err = os_unmap_memory((void *) addr, 390 err = add_munmap(addr, last - addr, &hvc);
363 last - addr);
364 if (err < 0) 391 if (err < 0)
365 panic("munmap failed, errno = %d\n", 392 panic("munmap failed, errno = %d\n",
366 -err); 393 -err);
@@ -372,22 +399,25 @@ static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
372 pte = pte_offset_kernel(pmd, addr); 399 pte = pte_offset_kernel(pmd, addr);
373 if (!pte_present(*pte) || pte_newpage(*pte)) { 400 if (!pte_present(*pte) || pte_newpage(*pte)) {
374 updated = 1; 401 updated = 1;
375 err = os_unmap_memory((void *) addr, 402 err = add_munmap(addr, PAGE_SIZE, &hvc);
376 PAGE_SIZE);
377 if (err < 0) 403 if (err < 0)
378 panic("munmap failed, errno = %d\n", 404 panic("munmap failed, errno = %d\n",
379 -err); 405 -err);
380 if (pte_present(*pte)) 406 if (pte_present(*pte))
381 map_memory(addr, 407 err = add_mmap(addr, pte_val(*pte) & PAGE_MASK,
382 pte_val(*pte) & PAGE_MASK, 408 PAGE_SIZE, 0, &hvc);
383 PAGE_SIZE, 1, 1, 1);
384 } 409 }
385 else if (pte_newprot(*pte)) { 410 else if (pte_newprot(*pte)) {
386 updated = 1; 411 updated = 1;
387 os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1); 412 err = add_mprotect(addr, PAGE_SIZE, 0, &hvc);
388 } 413 }
389 addr += PAGE_SIZE; 414 addr += PAGE_SIZE;
390 } 415 }
416 if (!err)
417 err = do_ops(&hvc, hvc.index, 1);
418
419 if (err < 0)
420 panic("flush_tlb_kernel failed, errno = %d\n", err);
391 return updated; 421 return updated;
392} 422}
393 423
@@ -491,6 +521,13 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr)
491 521
492void flush_tlb_all(void) 522void flush_tlb_all(void)
493{ 523{
524 /*
525 * Don't bother flushing if this address space is about to be
526 * destroyed.
527 */
528 if (atomic_read(&current->mm->mm_users) == 0)
529 return;
530
494 flush_tlb_mm(current->mm); 531 flush_tlb_mm(current->mm);
495} 532}
496 533
@@ -512,6 +549,13 @@ void __flush_tlb_one(unsigned long addr)
512static void fix_range(struct mm_struct *mm, unsigned long start_addr, 549static void fix_range(struct mm_struct *mm, unsigned long start_addr,
513 unsigned long end_addr, int force) 550 unsigned long end_addr, int force)
514{ 551{
552 /*
553 * Don't bother flushing if this address space is about to be
554 * destroyed.
555 */
556 if (atomic_read(&mm->mm_users) == 0)
557 return;
558
515 fix_range_common(mm, start_addr, end_addr, force); 559 fix_range_common(mm, start_addr, end_addr, force);
516} 560}
517 561
@@ -527,13 +571,6 @@ EXPORT_SYMBOL(flush_tlb_range);
527void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, 571void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
528 unsigned long end) 572 unsigned long end)
529{ 573{
530 /*
531 * Don't bother flushing if this address space is about to be
532 * destroyed.
533 */
534 if (atomic_read(&mm->mm_users) == 0)
535 return;
536
537 fix_range(mm, start, end, 0); 574 fix_range(mm, start, end, 0);
538} 575}
539 576
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index c0197097c86e..f25b110d4e70 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -610,3 +610,13 @@ unsigned long long os_makedev(unsigned major, unsigned minor)
610{ 610{
611 return makedev(major, minor); 611 return makedev(major, minor);
612} 612}
613
614int os_falloc_punch(int fd, unsigned long long offset, int len)
615{
616 int n = fallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, offset, len);
617
618 if (n < 0)
619 return -errno;
620 return n;
621}
622