Commit 6aa293d8 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 04a17ede 940b241d
...@@ -15951,15 +15951,16 @@ F: drivers/media/usb/zr364xx/ ...@@ -15951,15 +15951,16 @@ F: drivers/media/usb/zr364xx/
USER-MODE LINUX (UML) USER-MODE LINUX (UML)
M: Jeff Dike <jdike@addtoit.com> M: Jeff Dike <jdike@addtoit.com>
M: Richard Weinberger <richard@nod.at> M: Richard Weinberger <richard@nod.at>
M: Anton Ivanov <anton.ivanov@cambridgegreys.com>
L: linux-um@lists.infradead.org L: linux-um@lists.infradead.org
W: http://user-mode-linux.sourceforge.net 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/rw/uml.git
S: Maintained S: Maintained
F: Documentation/virtual/uml/ F: Documentation/virtual/uml/
F: arch/um/ F: arch/um/
F: arch/x86/um/ F: arch/x86/um/
F: fs/hostfs/ F: fs/hostfs/
F: fs/hppfs/
USERSPACE COPYIN/COPYOUT (UIOVEC) USERSPACE COPYIN/COPYOUT (UIOVEC)
M: Alexander Viro <viro@zeniv.linux.org.uk> M: Alexander Viro <viro@zeniv.linux.org.uk>
......
...@@ -12,6 +12,7 @@ config UML ...@@ -12,6 +12,7 @@ config UML
select HAVE_UID16 select HAVE_UID16
select HAVE_FUTEX_CMPXCHG if FUTEX select HAVE_FUTEX_CMPXCHG if FUTEX
select HAVE_DEBUG_KMEMLEAK select HAVE_DEBUG_KMEMLEAK
select HAVE_DEBUG_BUGVERBOSE
select GENERIC_IRQ_SHOW select GENERIC_IRQ_SHOW
select GENERIC_CPU_DEVICES select GENERIC_CPU_DEVICES
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
......
...@@ -16,6 +16,7 @@ config GPROF ...@@ -16,6 +16,7 @@ config GPROF
config GCOV config GCOV
bool "Enable gcov support" bool "Enable gcov support"
depends on DEBUG_INFO depends on DEBUG_INFO
depends on !KCOV
help help
This option allows developers to retrieve coverage data from a UML This option allows developers to retrieve coverage data from a UML
session. session.
......
...@@ -211,12 +211,6 @@ void deactivate_chan(struct chan *chan, int irq) ...@@ -211,12 +211,6 @@ void deactivate_chan(struct chan *chan, int irq)
deactivate_fd(chan->fd, irq); deactivate_fd(chan->fd, irq);
} }
void reactivate_chan(struct chan *chan, int irq)
{
if (chan && chan->enabled)
reactivate_fd(chan->fd, irq);
}
int write_chan(struct chan *chan, const char *buf, int len, int write_chan(struct chan *chan, const char *buf, int len,
int write_irq) int write_irq)
{ {
...@@ -228,8 +222,6 @@ int write_chan(struct chan *chan, const char *buf, int len, ...@@ -228,8 +222,6 @@ int write_chan(struct chan *chan, const char *buf, int len,
n = chan->ops->write(chan->fd, buf, len, chan->data); n = chan->ops->write(chan->fd, buf, len, chan->data);
if (chan->primary) { if (chan->primary) {
ret = n; ret = n;
if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len)))
reactivate_fd(chan->fd, write_irq);
} }
return ret; return ret;
} }
...@@ -527,8 +519,6 @@ void chan_interrupt(struct line *line, int irq) ...@@ -527,8 +519,6 @@ void chan_interrupt(struct line *line, int irq)
tty_insert_flip_char(port, c, TTY_NORMAL); tty_insert_flip_char(port, c, TTY_NORMAL);
} while (err > 0); } while (err > 0);
if (err == 0)
reactivate_fd(chan->fd, irq);
if (err == -EIO) { if (err == -EIO) {
if (chan->primary) { if (chan->primary) {
tty_port_tty_hangup(&line->port, false); tty_port_tty_hangup(&line->port, false);
......
...@@ -235,14 +235,6 @@ void line_unthrottle(struct tty_struct *tty) ...@@ -235,14 +235,6 @@ void line_unthrottle(struct tty_struct *tty)
line->throttled = 0; line->throttled = 0;
chan_interrupt(line, line->driver->read_irq); chan_interrupt(line, line->driver->read_irq);
/*
* Maybe there is enough stuff pending that calling the interrupt
* throttles us again. In this case, line->throttled will be 1
* again and we shouldn't turn the interrupt back on.
*/
if (!line->throttled)
reactivate_chan(line->chan_in, line->driver->read_irq);
} }
static irqreturn_t line_write_interrupt(int irq, void *data) static irqreturn_t line_write_interrupt(int irq, void *data)
...@@ -667,8 +659,6 @@ static irqreturn_t winch_interrupt(int irq, void *data) ...@@ -667,8 +659,6 @@ static irqreturn_t winch_interrupt(int irq, void *data)
tty_kref_put(tty); tty_kref_put(tty);
} }
out: out:
if (winch->fd != -1)
reactivate_fd(winch->fd, WINCH_IRQ);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -96,7 +96,6 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id) ...@@ -96,7 +96,6 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id)
} }
if (!list_empty(&mc_requests)) if (!list_empty(&mc_requests))
schedule_work(&mconsole_work); schedule_work(&mconsole_work);
reactivate_fd(fd, MCONSOLE_IRQ);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -240,7 +239,6 @@ void mconsole_stop(struct mc_request *req) ...@@ -240,7 +239,6 @@ void mconsole_stop(struct mc_request *req)
(*req->cmd->handler)(req); (*req->cmd->handler)(req);
} }
os_set_fd_block(req->originating_fd, 0); os_set_fd_block(req->originating_fd, 0);
reactivate_fd(req->originating_fd, MCONSOLE_IRQ);
mconsole_reply(req, "", 0, 0); mconsole_reply(req, "", 0, 0);
} }
......
...@@ -137,8 +137,6 @@ static irqreturn_t uml_net_interrupt(int irq, void *dev_id) ...@@ -137,8 +137,6 @@ static irqreturn_t uml_net_interrupt(int irq, void *dev_id)
schedule_work(&lp->work); schedule_work(&lp->work);
goto out; goto out;
} }
reactivate_fd(lp->fd, UM_ETH_IRQ);
out: out:
spin_unlock(&lp->lock); spin_unlock(&lp->lock);
return IRQ_HANDLED; return IRQ_HANDLED;
......
...@@ -137,7 +137,6 @@ static void port_work_proc(struct work_struct *unused) ...@@ -137,7 +137,6 @@ static void port_work_proc(struct work_struct *unused)
if (!port->has_connection) if (!port->has_connection)
continue; continue;
reactivate_fd(port->fd, ACCEPT_IRQ);
while (port_accept(port)) while (port_accept(port))
; ;
port->has_connection = 0; port->has_connection = 0;
......
...@@ -73,7 +73,6 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, ...@@ -73,7 +73,6 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
return ret ? : -EAGAIN; return ret ? : -EAGAIN;
atomic_inc(&host_sleep_count); atomic_inc(&host_sleep_count);
reactivate_fd(random_fd, RANDOM_IRQ);
add_sigio_fd(random_fd); add_sigio_fd(random_fd);
add_wait_queue(&host_read_wait, &wait); add_wait_queue(&host_read_wait, &wait);
......
This diff is collapsed.
...@@ -25,11 +25,13 @@ ...@@ -25,11 +25,13 @@
#include <linux/if_packet.h> #include <linux/if_packet.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/uio.h>
#include <linux/virtio_net.h> #include <linux/virtio_net.h>
#include <netdb.h> #include <netdb.h>
#include <stdlib.h> #include <stdlib.h>
#include <os.h> #include <os.h>
#include <um_malloc.h> #include <um_malloc.h>
#include <sys/uio.h>
#include "vector_user.h" #include "vector_user.h"
#define ID_GRE 0 #define ID_GRE 0
......
...@@ -10,9 +10,7 @@ generic-y += exec.h ...@@ -10,9 +10,7 @@ generic-y += exec.h
generic-y += extable.h generic-y += extable.h
generic-y += ftrace.h generic-y += ftrace.h
generic-y += futex.h generic-y += futex.h
generic-y += hardirq.h
generic-y += hw_irq.h generic-y += hw_irq.h
generic-y += io.h
generic-y += irq_regs.h generic-y += irq_regs.h
generic-y += irq_work.h generic-y += irq_work.h
generic-y += kdebug.h generic-y += kdebug.h
......
...@@ -197,12 +197,17 @@ static inline pte_t pte_mkold(pte_t pte) ...@@ -197,12 +197,17 @@ static inline pte_t pte_mkold(pte_t pte)
static inline pte_t pte_wrprotect(pte_t pte) static inline pte_t pte_wrprotect(pte_t pte)
{ {
pte_clear_bits(pte, _PAGE_RW); if (likely(pte_get_bits(pte, _PAGE_RW)))
pte_clear_bits(pte, _PAGE_RW);
else
return pte;
return(pte_mknewprot(pte)); return(pte_mknewprot(pte));
} }
static inline pte_t pte_mkread(pte_t pte) static inline pte_t pte_mkread(pte_t pte)
{ {
if (unlikely(pte_get_bits(pte, _PAGE_USER)))
return pte;
pte_set_bits(pte, _PAGE_USER); pte_set_bits(pte, _PAGE_USER);
return(pte_mknewprot(pte)); return(pte_mknewprot(pte));
} }
...@@ -221,6 +226,8 @@ static inline pte_t pte_mkyoung(pte_t pte) ...@@ -221,6 +226,8 @@ static inline pte_t pte_mkyoung(pte_t pte)
static inline pte_t pte_mkwrite(pte_t pte) static inline pte_t pte_mkwrite(pte_t pte)
{ {
if (unlikely(pte_get_bits(pte, _PAGE_RW)))
return pte;
pte_set_bits(pte, _PAGE_RW); pte_set_bits(pte, _PAGE_RW);
return(pte_mknewprot(pte)); return(pte_mknewprot(pte));
} }
......
...@@ -31,7 +31,6 @@ struct irq_fd { ...@@ -31,7 +31,6 @@ struct irq_fd {
struct siginfo; struct siginfo;
extern void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); extern void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs);
extern void free_irq_by_fd(int fd); extern void free_irq_by_fd(int fd);
extern void reactivate_fd(int fd, int irqnum);
extern void deactivate_fd(int fd, int irqnum); extern void deactivate_fd(int fd, int irqnum);
extern int deactivate_all_fds(void); extern int deactivate_all_fds(void);
extern int activate_ipi(int fd, int pid); extern int activate_ipi(int fd, int pid);
......
...@@ -175,6 +175,7 @@ extern int os_fchange_dir(int fd); ...@@ -175,6 +175,7 @@ extern int os_fchange_dir(int fd);
extern unsigned os_major(unsigned long long dev); extern unsigned os_major(unsigned long long dev);
extern unsigned os_minor(unsigned long long dev); extern unsigned os_minor(unsigned long long dev);
extern unsigned long long os_makedev(unsigned major, unsigned minor); extern unsigned long long os_makedev(unsigned major, unsigned minor);
extern int os_falloc_punch(int fd, unsigned long long offset, int count);
/* start_up.c */ /* start_up.c */
extern void os_early_checks(void); extern void os_early_checks(void);
......
...@@ -350,11 +350,6 @@ static void free_irq_by_irq_and_dev(unsigned int irq, void *dev) ...@@ -350,11 +350,6 @@ static void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
} }
void reactivate_fd(int fd, int irqnum)
{
/** NOP - we do auto-EOI now **/
}
void deactivate_fd(int fd, int irqnum) void deactivate_fd(int fd, int irqnum)
{ {
struct irq_entry *to_free; struct irq_entry *to_free;
...@@ -449,7 +444,6 @@ int um_request_irq(unsigned int irq, int fd, int type, ...@@ -449,7 +444,6 @@ int um_request_irq(unsigned int irq, int fd, int type,
} }
EXPORT_SYMBOL(um_request_irq); EXPORT_SYMBOL(um_request_irq);
EXPORT_SYMBOL(reactivate_fd);
/* /*
* irq_chip must define at least enable/disable and ack when * irq_chip must define at least enable/disable and ack when
......
...@@ -16,7 +16,6 @@ static irqreturn_t sigio_interrupt(int irq, void *data) ...@@ -16,7 +16,6 @@ static irqreturn_t sigio_interrupt(int irq, void *data)
char c; char c;
os_read_file(sigio_irq_fd, &c, sizeof(c)); os_read_file(sigio_irq_fd, &c, sizeof(c));
reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -62,27 +62,28 @@ static int do_op_one_page(unsigned long addr, int len, int is_write, ...@@ -62,27 +62,28 @@ static int do_op_one_page(unsigned long addr, int len, int is_write,
jmp_buf buf; jmp_buf buf;
struct page *page; struct page *page;
pte_t *pte; pte_t *pte;
int n, faulted; int n;
pte = maybe_map(addr, is_write); pte = maybe_map(addr, is_write);
if (pte == NULL) if (pte == NULL)
return -1; return -1;
page = pte_page(*pte); page = pte_page(*pte);
#ifdef CONFIG_64BIT
pagefault_disable();
addr = (unsigned long) page_address(page) +
(addr & ~PAGE_MASK);
#else
addr = (unsigned long) kmap_atomic(page) + addr = (unsigned long) kmap_atomic(page) +
(addr & ~PAGE_MASK); (addr & ~PAGE_MASK);
#endif
n = (*op)(addr, len, arg);
current->thread.fault_catcher = &buf; #ifdef CONFIG_64BIT
pagefault_enable();
faulted = UML_SETJMP(&buf); #else
if (faulted == 0)
n = (*op)(addr, len, arg);
else
n = -1;
current->thread.fault_catcher = NULL;
kunmap_atomic((void *)addr); kunmap_atomic((void *)addr);
#endif
return n; return n;
} }
......
...@@ -37,17 +37,19 @@ struct host_vm_change { ...@@ -37,17 +37,19 @@ struct host_vm_change {
} mprotect; } mprotect;
} u; } u;
} ops[1]; } ops[1];
int userspace;
int index; int index;
struct mm_id *id; struct mm_struct *mm;
void *data; void *data;
int force; int force;
}; };
#define INIT_HVC(mm, force) \ #define INIT_HVC(mm, force, userspace) \
((struct host_vm_change) \ ((struct host_vm_change) \
{ .ops = { { .type = NONE } }, \ { .ops = { { .type = NONE } }, \
.id = &mm->context.id, \ .mm = mm, \
.data = NULL, \ .data = NULL, \
.userspace = userspace, \
.index = 0, \ .index = 0, \
.force = force }) .force = force })
...@@ -68,18 +70,40 @@ static int do_ops(struct host_vm_change *hvc, int end, ...@@ -68,18 +70,40 @@ static int do_ops(struct host_vm_change *hvc, int end,
op = &hvc->ops[i]; op = &hvc->ops[i];
switch (op->type) { switch (op->type) {
case MMAP: case MMAP:
ret = map(hvc->id, op->u.mmap.addr, op->u.mmap.len, if (hvc->userspace)
op->u.mmap.prot, op->u.mmap.fd, ret = map(&hvc->mm->context.id, op->u.mmap.addr,
op->u.mmap.offset, finished, &hvc->data); op->u.mmap.len, op->u.mmap.prot,
op->u.mmap.fd,
op->u.mmap.offset, finished,
&hvc->data);
else
map_memory(op->u.mmap.addr, op->u.mmap.offset,
op->u.mmap.len, 1, 1, 1);
break; break;
case MUNMAP: case MUNMAP:
ret = unmap(hvc->id, op->u.munmap.addr, if (hvc->userspace)
op->u.munmap.len, finished, &hvc->data); ret = unmap(&hvc->mm->context.id,
op->u.munmap.addr,
op->u.munmap.len, finished,
&hvc->data);
else
ret = os_unmap_memory(
(void *) op->u.munmap.addr,
op->u.munmap.len);
break; break;
case MPROTECT: case MPROTECT:
ret = protect(hvc->id, op->u.mprotect.addr, if (hvc->userspace)
op->u.mprotect.len, op->u.mprotect.prot, ret = protect(&hvc->mm->context.id,
finished, &hvc->data); op->u.mprotect.addr,
op->u.mprotect.len,
op->u.mprotect.prot,
finished, &hvc->data);
else
ret = os_protect_memory(
(void *) op->u.mprotect.addr,
op->u.mprotect.len,
1, 1, 1);
break; break;
default: default:
printk(KERN_ERR "Unknown op type %d in do_ops\n", 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,9 +124,12 @@ static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
{ {
__u64 offset; __u64 offset;
struct host_vm_op *last; struct host_vm_op *last;
int fd, ret = 0; int fd = -1, ret = 0;
fd = phys_mapping(phys, &offset); if (hvc->userspace)
fd = phys_mapping(phys, &offset);
else
offset = phys;
if (hvc->index != 0) { if (hvc->index != 0) {
last = &hvc->ops[hvc->index - 1]; last = &hvc->ops[hvc->index - 1];
if ((last->type == MMAP) && if ((last->type == MMAP) &&
...@@ -215,10 +242,11 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr, ...@@ -215,10 +242,11 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
(x ? UM_PROT_EXEC : 0)); (x ? UM_PROT_EXEC : 0));
if (hvc->force || pte_newpage(*pte)) { if (hvc->force || pte_newpage(*pte)) {
if (pte_present(*pte)) if (pte_present(*pte)) {
ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK, if (pte_newpage(*pte))
PAGE_SIZE, prot, hvc); ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK,
else PAGE_SIZE, prot, hvc);
} else
ret = add_munmap(addr, PAGE_SIZE, hvc); ret = add_munmap(addr, PAGE_SIZE, hvc);
} else if (pte_newprot(*pte)) } else if (pte_newprot(*pte))
ret = add_mprotect(addr, PAGE_SIZE, prot, hvc); 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,9 +305,9 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
pgd_t *pgd; pgd_t *pgd;
struct host_vm_change hvc; struct host_vm_change hvc;
unsigned long addr = start_addr, next; unsigned long addr = start_addr, next;
int ret = 0; int ret = 0, userspace = 1;
hvc = INIT_HVC(mm, force); hvc = INIT_HVC(mm, force, userspace);
pgd = pgd_offset(mm, addr); pgd = pgd_offset(mm, addr);
do { do {
next = pgd_addr_end(addr, end_addr); 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,9 +342,11 @@ static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
pmd_t *pmd; pmd_t *pmd;
pte_t *pte; pte_t *pte;
unsigned long addr, last; unsigned long addr, last;
int updated = 0, err; int updated = 0, err = 0, force = 0, userspace = 0;
struct host_vm_change hvc;
mm = &init_mm; mm = &init_mm;
hvc = INIT_HVC(mm, force, userspace);
for (addr = start; addr < end;) { for (addr = start; addr < end;) {
pgd = pgd_offset(mm, addr); pgd = pgd_offset(mm, addr);
if (!pgd_present(*pgd)) { if (!pgd_present(*pgd)) {
...@@ -325,8 +355,7 @@ static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) ...@@ -325,8 +355,7 @@ static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
last = end; last = end;
if (pgd_newpage(*pgd)) { if (pgd_newpage(*pgd)) {
updated = 1; updated = 1;
err = os_unmap_memory((void *) addr, err = add_munmap(addr, last - addr, &hvc);
last - addr);
if (err < 0) if (err < 0)
panic("munmap failed, errno = %d\n", panic("munmap failed, errno = %d\n",
-err); -err);
...@@ -342,8 +371,7 @@ static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) ...@@ -342,8 +371,7 @@ static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
last = end; last = end;
if (pud_newpage(*pud)) { if (pud_newpage(*pud)) {
updated = 1; updated = 1;
err = os_unmap_memory((void *) addr, err = add_munmap(addr, last - addr, &hvc);
last - addr);
if (err < 0) if (err < 0)
panic("munmap failed, errno = %d\n", panic("munmap failed, errno = %d\n",
-err); -err);
...@@ -359,8 +387,7 @@ static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) ...@@ -359,8 +387,7 @@ static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
last = end; last = end;
if (pmd_newpage(*pmd)) { if (pmd_newpage(*pmd)) {
updated = 1; updated = 1;
err = os_unmap_memory((void *) addr, err = add_munmap(addr, last - addr, &hvc);
last - addr);
if (err < 0) if (err < 0)
panic("munmap failed, errno = %d\n", panic("munmap failed, errno = %d\n",
-err); -err);
...@@ -372,22 +399,25 @@ static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) ...@@ -372,22 +399,25 @@ static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
pte = pte_offset_kernel(pmd, addr); pte = pte_offset_kernel(pmd, addr);
if (!pte_present(*pte) || pte_newpage(*pte)) { if (!pte_present(*pte) || pte_newpage(*pte)) {
updated = 1; updated = 1;
err = os_unmap_memory((void *) addr, err = add_munmap(addr, PAGE_SIZE, &hvc);
PAGE_SIZE);
if (err < 0) if (err < 0)
panic("munmap failed, errno = %d\n", panic("munmap failed, errno = %d\n",
-err); -err);
if (pte_present(*pte)) if (pte_present(*pte))
map_memory(addr, err = add_mmap(addr, pte_val(*pte) & PAGE_MASK,
pte_val(*pte) & PAGE_MASK, PAGE_SIZE, 0, &hvc);
PAGE_SIZE, 1, 1, 1);
} }
else if (pte_newprot(*pte)) { else if (pte_newprot(*pte)) {
updated = 1; updated = 1;
os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1); err = add_mprotect(addr, PAGE_SIZE, 0, &hvc);
} }
addr += PAGE_SIZE; addr += PAGE_SIZE;
} }
if (!err)
err = do_ops(&hvc, hvc.index, 1);
if (err < 0)
panic("flush_tlb_kernel failed, errno = %d\n", err);
return updated; return updated;
} }
...@@ -491,6 +521,13 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr) ...@@ -491,6 +521,13 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr)
void flush_tlb_all(void) void flush_tlb_all(void)
{ {
/*
* Don't bother flushing if this address space is about to be
* destroyed.
*/
if (atomic_read(&current->mm->mm_users) == 0)
return;
flush_tlb_mm(current->mm); flush_tlb_mm(current->mm);
} }
...@@ -512,6 +549,13 @@ void __flush_tlb_one(unsigned long addr) ...@@ -512,6 +549,13 @@ void __flush_tlb_one(unsigned long addr)
static void fix_range(struct mm_struct *mm, unsigned long start_addr, static void fix_range(struct mm_struct *mm, unsigned long start_addr,
unsigned long end_addr, int force) unsigned long end_addr, int force)
{ {
/*
* Don't bother flushing if this address space is about to be
* destroyed.
*/
if (atomic_read(&mm->mm_users) == 0)
return;
fix_range_common(mm, start_addr, end_addr, force); fix_range_common(mm, start_addr, end_addr, force);
} }
...@@ -527,13 +571,6 @@ EXPORT_SYMBOL(flush_tlb_range); ...@@ -527,13 +571,6 @@ EXPORT_SYMBOL(flush_tlb_range);
void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
unsigned long end) unsigned long end)
{ {
/*
* Don't bother flushing if this address space is about to be
* destroyed.
*/
if (atomic_read(&mm->mm_users) == 0)
return;
fix_range(mm, start, end, 0); fix_range(mm, start, end, 0);
} }
......
...@@ -610,3 +610,13 @@ unsigned long long os_makedev(unsigned major, unsigned minor) ...@@ -610,3 +610,13 @@ unsigned long long os_makedev(unsigned major, unsigned minor)
{ {
return makedev(major, minor); return makedev(major, minor);
} }
int os_falloc_punch(int fd, unsigned long long offset, int len)
{
int n = fallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, offset, len);
if (n < 0)
return -errno;
return n;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment