mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge tag 'uml-for-linus-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/uml/linux
Pull UML updates from Richard Weinberger: - Lots of cleanups, mostly from Benjamin Berg and Tiwei Bie - Removal of unused code - Fix for sparse warnings - Cleanup around stub_exe() * tag 'uml-for-linus-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/uml/linux: (68 commits) hostfs: Fix the NULL vs IS_ERR() bug for __filemap_get_folio() um: move thread info into task um: Always dump trace for specified task in show_stack um: vector: Do not use drvdata in release um: net: Do not use drvdata in release um: ubd: Do not use drvdata in release um: ubd: Initialize ubd's disk pointer in ubd_add um: virtio_uml: query the number of vqs if supported um: virtio_uml: fix call_fd IRQ allocation um: virtio_uml: send SET_MEM_TABLE message with the exact size um: remove broken double fault detection um: remove duplicate UM_NSEC_PER_SEC definition um: remove file sync for stub data um: always include kconfig.h and compiler-version.h um: set DONTDUMP and DONTFORK flags on KASAN shadow memory um: fix sparse warnings in signal code um: fix sparse warnings from regset refactor um: Remove double zero check um: fix stub exe build with CONFIG_GCOV um: Use os_set_pdeathsig helper in winch thread/process ...
This commit is contained in:
@@ -5,6 +5,7 @@ menu "UML-specific options"
|
||||
config UML
|
||||
bool
|
||||
default y
|
||||
select ARCH_WANTS_DYNAMIC_TASK_STRUCT
|
||||
select ARCH_HAS_CPU_FINALIZE_INIT
|
||||
select ARCH_HAS_FORTIFY_SOURCE
|
||||
select ARCH_HAS_GCOV_PROFILE_ALL
|
||||
@@ -32,6 +33,8 @@ config UML
|
||||
select HAVE_ARCH_VMAP_STACK
|
||||
select HAVE_RUST
|
||||
select ARCH_HAS_UBSAN
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select THREAD_INFO_IN_TASK
|
||||
|
||||
config MMU
|
||||
bool
|
||||
@@ -94,7 +97,7 @@ config MAY_HAVE_RUNTIME_DEPS
|
||||
|
||||
config STATIC_LINK
|
||||
bool "Force a static link"
|
||||
depends on CC_CAN_LINK_STATIC_NO_RUNTIME_DEPS || !MAY_HAVE_RUNTIME_DEPS
|
||||
depends on !MAY_HAVE_RUNTIME_DEPS
|
||||
help
|
||||
This option gives you the ability to force a static link of UML.
|
||||
Normally, UML is linked as a shared binary. This is inconvenient for
|
||||
@@ -209,8 +212,8 @@ config MMAPPER
|
||||
|
||||
config PGTABLE_LEVELS
|
||||
int
|
||||
default 3 if 3_LEVEL_PGTABLES
|
||||
default 2
|
||||
default 4 if 64BIT
|
||||
default 2 if !64BIT
|
||||
|
||||
config UML_TIME_TRAVEL_SUPPORT
|
||||
bool
|
||||
@@ -227,6 +230,21 @@ config UML_TIME_TRAVEL_SUPPORT
|
||||
|
||||
It is safe to say Y, but you probably don't need this.
|
||||
|
||||
config UML_MAX_USERSPACE_ITERATIONS
|
||||
int
|
||||
prompt "Maximum number of unscheduled userspace iterations"
|
||||
default 10000
|
||||
depends on UML_TIME_TRAVEL_SUPPORT
|
||||
help
|
||||
In UML inf-cpu and ext time-travel mode userspace can run without being
|
||||
interrupted. This will eventually overwhelm the kernel and create OOM
|
||||
situations (mainly RCU not running). This setting specifies the number
|
||||
of kernel/userspace switches (minor/major page fault, signal or syscall)
|
||||
for the same userspace thread before the sched_clock is advanced by a
|
||||
jiffie to trigger scheduling.
|
||||
|
||||
Setting it to zero disables the feature.
|
||||
|
||||
config KASAN_SHADOW_OFFSET
|
||||
hex
|
||||
depends on KASAN
|
||||
|
||||
@@ -61,7 +61,8 @@ KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ \
|
||||
$(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \
|
||||
-Dlongjmp=kernel_longjmp -Dsetjmp=kernel_setjmp \
|
||||
-Din6addr_loopback=kernel_in6addr_loopback \
|
||||
-Din6addr_any=kernel_in6addr_any -Dstrrchr=kernel_strrchr
|
||||
-Din6addr_any=kernel_in6addr_any -Dstrrchr=kernel_strrchr \
|
||||
-D__close_range=kernel__close_range
|
||||
|
||||
KBUILD_RUSTFLAGS += -Crelocation-model=pie
|
||||
|
||||
@@ -70,7 +71,9 @@ KBUILD_AFLAGS += $(ARCH_INCLUDE)
|
||||
USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \
|
||||
$(ARCH_INCLUDE) $(MODE_INCLUDE) $(filter -I%,$(CFLAGS)) \
|
||||
-D_FILE_OFFSET_BITS=64 -idirafter $(srctree)/include \
|
||||
-idirafter $(objtree)/include -D__KERNEL__ -D__UM_HOST__
|
||||
-idirafter $(objtree)/include -D__KERNEL__ -D__UM_HOST__ \
|
||||
-include $(srctree)/include/linux/compiler-version.h \
|
||||
-include $(srctree)/include/linux/kconfig.h
|
||||
|
||||
#This will adjust *FLAGS accordingly to the platform.
|
||||
include $(srctree)/$(ARCH_DIR)/Makefile-os-Linux
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
# Licensed under the GPL
|
||||
#
|
||||
|
||||
GPROF_OPT += -pg
|
||||
export UM_GPROF_OPT += -pg
|
||||
|
||||
ifdef CONFIG_CC_IS_CLANG
|
||||
GCOV_OPT += -fprofile-instr-generate -fcoverage-mapping
|
||||
export UM_GCOV_OPT += -fprofile-instr-generate -fcoverage-mapping
|
||||
else
|
||||
GCOV_OPT += -fprofile-arcs -ftest-coverage
|
||||
export UM_GCOV_OPT += -fprofile-arcs -ftest-coverage
|
||||
endif
|
||||
|
||||
CFLAGS-$(CONFIG_GCOV) += $(GCOV_OPT)
|
||||
CFLAGS-$(CONFIG_GPROF) += $(GPROF_OPT)
|
||||
LINK-$(CONFIG_GCOV) += $(GCOV_OPT)
|
||||
LINK-$(CONFIG_GPROF) += $(GPROF_OPT)
|
||||
CFLAGS-$(CONFIG_GCOV) += $(UM_GCOV_OPT)
|
||||
CFLAGS-$(CONFIG_GPROF) += $(UM_GPROF_OPT)
|
||||
LINK-$(CONFIG_GCOV) += $(UM_GCOV_OPT)
|
||||
LINK-$(CONFIG_GPROF) += $(UM_GPROF_OPT)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
CONFIG_3_LEVEL_PGTABLES=y
|
||||
# CONFIG_COMPACTION is not set
|
||||
CONFIG_BINFMT_MISC=m
|
||||
CONFIG_HOSTFS=y
|
||||
|
||||
@@ -161,6 +161,8 @@ static __noreturn int winch_thread(void *arg)
|
||||
int count;
|
||||
char c = 1;
|
||||
|
||||
os_set_pdeathsig();
|
||||
|
||||
pty_fd = data->pty_fd;
|
||||
pipe_fd = data->pipe_fd;
|
||||
count = write(pipe_fd, &c, sizeof(c));
|
||||
|
||||
@@ -48,6 +48,7 @@ MODULE_PARM_DESC(mixer, MIXER_HELP);
|
||||
#ifndef MODULE
|
||||
static int set_dsp(char *name, int *add)
|
||||
{
|
||||
*add = 0;
|
||||
dsp = name;
|
||||
return 0;
|
||||
}
|
||||
@@ -56,6 +57,7 @@ __uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP);
|
||||
|
||||
static int set_mixer(char *name, int *add)
|
||||
{
|
||||
*add = 0;
|
||||
mixer = name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -336,7 +336,7 @@ static struct platform_driver uml_net_driver = {
|
||||
|
||||
static void net_device_release(struct device *dev)
|
||||
{
|
||||
struct uml_net *device = dev_get_drvdata(dev);
|
||||
struct uml_net *device = container_of(dev, struct uml_net, pdev.dev);
|
||||
struct net_device *netdev = device->dev;
|
||||
struct uml_net_private *lp = netdev_priv(netdev);
|
||||
|
||||
|
||||
@@ -779,7 +779,7 @@ static int ubd_open_dev(struct ubd *ubd_dev)
|
||||
|
||||
static void ubd_device_release(struct device *dev)
|
||||
{
|
||||
struct ubd *ubd_dev = dev_get_drvdata(dev);
|
||||
struct ubd *ubd_dev = container_of(dev, struct ubd, pdev.dev);
|
||||
|
||||
blk_mq_free_tag_set(&ubd_dev->tag_set);
|
||||
*ubd_dev = ((struct ubd) DEFAULT_UBD);
|
||||
@@ -898,6 +898,8 @@ static int ubd_add(int n, char **error_out)
|
||||
if (err)
|
||||
goto out_cleanup_disk;
|
||||
|
||||
ubd_dev->disk = disk;
|
||||
|
||||
return 0;
|
||||
|
||||
out_cleanup_disk:
|
||||
@@ -1499,6 +1501,7 @@ int io_thread(void *arg)
|
||||
{
|
||||
int n, count, written, res;
|
||||
|
||||
os_set_pdeathsig();
|
||||
os_fix_helper_signals();
|
||||
|
||||
while(1){
|
||||
|
||||
@@ -815,7 +815,8 @@ static struct platform_driver uml_net_driver = {
|
||||
|
||||
static void vector_device_release(struct device *dev)
|
||||
{
|
||||
struct vector_device *device = dev_get_drvdata(dev);
|
||||
struct vector_device *device =
|
||||
container_of(dev, struct vector_device, pdev.dev);
|
||||
struct net_device *netdev = device->dev;
|
||||
|
||||
list_del(&device->list);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
/* Feature bits */
|
||||
#define VHOST_USER_F_PROTOCOL_FEATURES 30
|
||||
/* Protocol feature bits */
|
||||
#define VHOST_USER_PROTOCOL_F_MQ 0
|
||||
#define VHOST_USER_PROTOCOL_F_REPLY_ACK 3
|
||||
#define VHOST_USER_PROTOCOL_F_SLAVE_REQ 5
|
||||
#define VHOST_USER_PROTOCOL_F_CONFIG 9
|
||||
@@ -23,7 +24,8 @@
|
||||
/* Supported transport features */
|
||||
#define VHOST_USER_SUPPORTED_F BIT_ULL(VHOST_USER_F_PROTOCOL_FEATURES)
|
||||
/* Supported protocol features */
|
||||
#define VHOST_USER_SUPPORTED_PROTOCOL_F (BIT_ULL(VHOST_USER_PROTOCOL_F_REPLY_ACK) | \
|
||||
#define VHOST_USER_SUPPORTED_PROTOCOL_F (BIT_ULL(VHOST_USER_PROTOCOL_F_MQ) | \
|
||||
BIT_ULL(VHOST_USER_PROTOCOL_F_REPLY_ACK) | \
|
||||
BIT_ULL(VHOST_USER_PROTOCOL_F_SLAVE_REQ) | \
|
||||
BIT_ULL(VHOST_USER_PROTOCOL_F_CONFIG) | \
|
||||
BIT_ULL(VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS))
|
||||
|
||||
@@ -56,6 +56,7 @@ struct virtio_uml_device {
|
||||
int sock, req_fd, irq;
|
||||
u64 features;
|
||||
u64 protocol_features;
|
||||
u64 max_vqs;
|
||||
u8 status;
|
||||
u8 registered:1;
|
||||
u8 suspended:1;
|
||||
@@ -72,8 +73,6 @@ struct virtio_uml_vq_info {
|
||||
bool suspended;
|
||||
};
|
||||
|
||||
extern unsigned long long physmem_size, highmem;
|
||||
|
||||
#define vu_err(vu_dev, ...) dev_err(&(vu_dev)->pdev->dev, ##__VA_ARGS__)
|
||||
|
||||
/* Vhost-user protocol */
|
||||
@@ -343,6 +342,17 @@ static int vhost_user_set_protocol_features(struct virtio_uml_device *vu_dev,
|
||||
protocol_features);
|
||||
}
|
||||
|
||||
static int vhost_user_get_queue_num(struct virtio_uml_device *vu_dev,
|
||||
u64 *queue_num)
|
||||
{
|
||||
int rc = vhost_user_send_no_payload(vu_dev, true,
|
||||
VHOST_USER_GET_QUEUE_NUM);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
return vhost_user_recv_u64(vu_dev, queue_num);
|
||||
}
|
||||
|
||||
static void vhost_user_reply(struct virtio_uml_device *vu_dev,
|
||||
struct vhost_user_msg *msg, int response)
|
||||
{
|
||||
@@ -516,6 +526,15 @@ static int vhost_user_init(struct virtio_uml_device *vu_dev)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (vu_dev->protocol_features &
|
||||
BIT_ULL(VHOST_USER_PROTOCOL_F_MQ)) {
|
||||
rc = vhost_user_get_queue_num(vu_dev, &vu_dev->max_vqs);
|
||||
if (rc)
|
||||
return rc;
|
||||
} else {
|
||||
vu_dev->max_vqs = U64_MAX;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -625,7 +644,7 @@ static int vhost_user_set_mem_table(struct virtio_uml_device *vu_dev)
|
||||
{
|
||||
struct vhost_user_msg msg = {
|
||||
.header.request = VHOST_USER_SET_MEM_TABLE,
|
||||
.header.size = sizeof(msg.payload.mem_regions),
|
||||
.header.size = offsetof(typeof(msg.payload.mem_regions), regions[1]),
|
||||
.payload.mem_regions.num = 1,
|
||||
};
|
||||
unsigned long reserved = uml_reserved - uml_physmem;
|
||||
@@ -673,13 +692,6 @@ static int vhost_user_set_mem_table(struct virtio_uml_device *vu_dev)
|
||||
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
if (highmem) {
|
||||
msg.payload.mem_regions.num++;
|
||||
rc = vhost_user_init_mem_region(__pa(end_iomem), highmem,
|
||||
&fds[1], &msg.payload.mem_regions.regions[1]);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return vhost_user_send(vu_dev, false, &msg, fds,
|
||||
msg.payload.mem_regions.num);
|
||||
@@ -897,7 +909,7 @@ static int vu_setup_vq_call_fd(struct virtio_uml_device *vu_dev,
|
||||
{
|
||||
struct virtio_uml_vq_info *info = vq->priv;
|
||||
int call_fds[2];
|
||||
int rc;
|
||||
int rc, irq;
|
||||
|
||||
/* no call FD needed/desired in this case */
|
||||
if (vu_dev->protocol_features &
|
||||
@@ -914,19 +926,23 @@ static int vu_setup_vq_call_fd(struct virtio_uml_device *vu_dev,
|
||||
return rc;
|
||||
|
||||
info->call_fd = call_fds[0];
|
||||
rc = um_request_irq(vu_dev->irq, info->call_fd, IRQ_READ,
|
||||
vu_interrupt, IRQF_SHARED, info->name, vq);
|
||||
if (rc < 0)
|
||||
irq = um_request_irq(vu_dev->irq, info->call_fd, IRQ_READ,
|
||||
vu_interrupt, IRQF_SHARED, info->name, vq);
|
||||
if (irq < 0) {
|
||||
rc = irq;
|
||||
goto close_both;
|
||||
}
|
||||
|
||||
rc = vhost_user_set_vring_call(vu_dev, vq->index, call_fds[1]);
|
||||
if (rc)
|
||||
goto release_irq;
|
||||
|
||||
vu_dev->irq = irq;
|
||||
|
||||
goto out;
|
||||
|
||||
release_irq:
|
||||
um_free_irq(vu_dev->irq, vq);
|
||||
um_free_irq(irq, vq);
|
||||
close_both:
|
||||
os_close_file(call_fds[0]);
|
||||
out:
|
||||
@@ -1023,7 +1039,9 @@ static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
|
||||
struct virtqueue *vq;
|
||||
|
||||
/* not supported for now */
|
||||
if (WARN_ON(nvqs > 64))
|
||||
if (WARN(nvqs > 64 || nvqs > vu_dev->max_vqs,
|
||||
"%d VQs requested, only up to 64 or %lld supported\n",
|
||||
nvqs, vu_dev->max_vqs))
|
||||
return -EINVAL;
|
||||
|
||||
rc = vhost_user_set_mem_table(vu_dev);
|
||||
@@ -1210,6 +1228,7 @@ static int virtio_uml_probe(struct platform_device *pdev)
|
||||
vu_dev->vdev.id.vendor = VIRTIO_DEV_ANY_ID;
|
||||
vu_dev->pdev = pdev;
|
||||
vu_dev->req_fd = -1;
|
||||
vu_dev->irq = UM_IRQ_ALLOC;
|
||||
|
||||
time_travel_propagate_time();
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
generic-y += bug.h
|
||||
generic-y += compat.h
|
||||
generic-y += current.h
|
||||
generic-y += device.h
|
||||
generic-y += dma-mapping.h
|
||||
generic-y += emergency-restart.h
|
||||
|
||||
23
arch/um/include/asm/current.h
Normal file
23
arch/um/include/asm/current.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_CURRENT_H
|
||||
#define __ASM_CURRENT_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/threads.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
struct task_struct;
|
||||
extern struct task_struct *cpu_tasks[NR_CPUS];
|
||||
|
||||
static __always_inline struct task_struct *get_current(void)
|
||||
{
|
||||
return cpu_tasks[0];
|
||||
}
|
||||
|
||||
|
||||
#define current get_current()
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __ASM_CURRENT_H */
|
||||
@@ -29,51 +29,35 @@ struct page;
|
||||
#define clear_user_page(page, vaddr, pg) clear_page(page)
|
||||
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
|
||||
|
||||
#if defined(CONFIG_3_LEVEL_PGTABLES) && !defined(CONFIG_64BIT)
|
||||
|
||||
typedef struct { unsigned long pte; } pte_t;
|
||||
typedef struct { unsigned long pmd; } pmd_t;
|
||||
typedef struct { unsigned long pgd; } pgd_t;
|
||||
#define pte_val(p) ((p).pte)
|
||||
|
||||
#define pte_get_bits(p, bits) ((p).pte & (bits))
|
||||
#define pte_set_bits(p, bits) ((p).pte |= (bits))
|
||||
#define pte_clear_bits(p, bits) ((p).pte &= ~(bits))
|
||||
#define pte_copy(to, from) ({ (to).pte = (from).pte; })
|
||||
#define pte_is_zero(p) (!((p).pte & ~_PAGE_NEWPAGE))
|
||||
#define pte_set_val(p, phys, prot) \
|
||||
({ (p).pte = (phys) | pgprot_val(prot); })
|
||||
|
||||
#define pmd_val(x) ((x).pmd)
|
||||
#define __pmd(x) ((pmd_t) { (x) } )
|
||||
|
||||
typedef unsigned long long phys_t;
|
||||
|
||||
#else
|
||||
|
||||
typedef struct { unsigned long pte; } pte_t;
|
||||
typedef struct { unsigned long pgd; } pgd_t;
|
||||
|
||||
#ifdef CONFIG_3_LEVEL_PGTABLES
|
||||
#if CONFIG_PGTABLE_LEVELS > 2
|
||||
|
||||
typedef struct { unsigned long pmd; } pmd_t;
|
||||
#define pmd_val(x) ((x).pmd)
|
||||
#define __pmd(x) ((pmd_t) { (x) } )
|
||||
#endif
|
||||
|
||||
#if CONFIG_PGTABLE_LEVELS > 3
|
||||
|
||||
typedef struct { unsigned long pud; } pud_t;
|
||||
#define pud_val(x) ((x).pud)
|
||||
#define __pud(x) ((pud_t) { (x) } )
|
||||
|
||||
#endif /* CONFIG_PGTABLE_LEVELS > 3 */
|
||||
#endif /* CONFIG_PGTABLE_LEVELS > 2 */
|
||||
|
||||
#define pte_val(x) ((x).pte)
|
||||
|
||||
|
||||
#define pte_get_bits(p, bits) ((p).pte & (bits))
|
||||
#define pte_set_bits(p, bits) ((p).pte |= (bits))
|
||||
#define pte_clear_bits(p, bits) ((p).pte &= ~(bits))
|
||||
#define pte_copy(to, from) ((to).pte = (from).pte)
|
||||
#define pte_is_zero(p) (!((p).pte & ~_PAGE_NEWPAGE))
|
||||
#define pte_is_zero(p) (!((p).pte & ~_PAGE_NEEDSYNC))
|
||||
#define pte_set_val(p, phys, prot) (p).pte = (phys | pgprot_val(prot))
|
||||
|
||||
typedef unsigned long phys_t;
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct { unsigned long pgprot; } pgprot_t;
|
||||
|
||||
typedef struct page *pgtable_t;
|
||||
|
||||
@@ -31,7 +31,7 @@ do { \
|
||||
tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \
|
||||
} while (0)
|
||||
|
||||
#ifdef CONFIG_3_LEVEL_PGTABLES
|
||||
#if CONFIG_PGTABLE_LEVELS > 2
|
||||
|
||||
#define __pmd_free_tlb(tlb, pmd, address) \
|
||||
do { \
|
||||
@@ -39,6 +39,15 @@ do { \
|
||||
tlb_remove_page_ptdesc((tlb), virt_to_ptdesc(pmd)); \
|
||||
} while (0)
|
||||
|
||||
#if CONFIG_PGTABLE_LEVELS > 3
|
||||
|
||||
#define __pud_free_tlb(tlb, pud, address) \
|
||||
do { \
|
||||
pagetable_pud_dtor(virt_to_ptdesc(pud)); \
|
||||
tlb_remove_page_ptdesc((tlb), virt_to_ptdesc(pud)); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
printk("%s:%d: bad pgd %p(%08lx).\n", __FILE__, __LINE__, &(e), \
|
||||
pgd_val(e))
|
||||
|
||||
static inline int pgd_newpage(pgd_t pgd) { return 0; }
|
||||
static inline int pgd_needsync(pgd_t pgd) { return 0; }
|
||||
static inline void pgd_mkuptodate(pgd_t pgd) { }
|
||||
|
||||
#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
|
||||
|
||||
@@ -4,21 +4,25 @@
|
||||
* Derived from include/asm-i386/pgtable.h
|
||||
*/
|
||||
|
||||
#ifndef __UM_PGTABLE_3LEVEL_H
|
||||
#define __UM_PGTABLE_3LEVEL_H
|
||||
#ifndef __UM_PGTABLE_4LEVEL_H
|
||||
#define __UM_PGTABLE_4LEVEL_H
|
||||
|
||||
#include <asm-generic/pgtable-nopud.h>
|
||||
#include <asm-generic/pgtable-nop4d.h>
|
||||
|
||||
/* PGDIR_SHIFT determines what a third-level page table entry can map */
|
||||
/* PGDIR_SHIFT determines what a fourth-level page table entry can map */
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
#define PGDIR_SHIFT 30
|
||||
#else
|
||||
#define PGDIR_SHIFT 31
|
||||
#endif
|
||||
#define PGDIR_SHIFT 39
|
||||
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
|
||||
#define PGDIR_MASK (~(PGDIR_SIZE-1))
|
||||
|
||||
/* PUD_SHIFT determines the size of the area a third-level page table can
|
||||
* map
|
||||
*/
|
||||
|
||||
#define PUD_SHIFT 30
|
||||
#define PUD_SIZE (1UL << PUD_SHIFT)
|
||||
#define PUD_MASK (~(PUD_SIZE-1))
|
||||
|
||||
/* PMD_SHIFT determines the size of the area a second-level page table can
|
||||
* map
|
||||
*/
|
||||
@@ -32,13 +36,9 @@
|
||||
*/
|
||||
|
||||
#define PTRS_PER_PTE 512
|
||||
#ifdef CONFIG_64BIT
|
||||
#define PTRS_PER_PMD 512
|
||||
#define PTRS_PER_PUD 512
|
||||
#define PTRS_PER_PGD 512
|
||||
#else
|
||||
#define PTRS_PER_PMD 1024
|
||||
#define PTRS_PER_PGD 1024
|
||||
#endif
|
||||
|
||||
#define USER_PTRS_PER_PGD ((TASK_SIZE + (PGDIR_SIZE - 1)) / PGDIR_SIZE)
|
||||
|
||||
@@ -48,11 +48,14 @@
|
||||
#define pmd_ERROR(e) \
|
||||
printk("%s:%d: bad pmd %p(%016lx).\n", __FILE__, __LINE__, &(e), \
|
||||
pmd_val(e))
|
||||
#define pud_ERROR(e) \
|
||||
printk("%s:%d: bad pud %p(%016lx).\n", __FILE__, __LINE__, &(e), \
|
||||
pud_val(e))
|
||||
#define pgd_ERROR(e) \
|
||||
printk("%s:%d: bad pgd %p(%016lx).\n", __FILE__, __LINE__, &(e), \
|
||||
pgd_val(e))
|
||||
|
||||
#define pud_none(x) (!(pud_val(x) & ~_PAGE_NEWPAGE))
|
||||
#define pud_none(x) (!(pud_val(x) & ~_PAGE_NEEDSYNC))
|
||||
#define pud_bad(x) ((pud_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
|
||||
#define pud_present(x) (pud_val(x) & _PAGE_PRESENT)
|
||||
#define pud_populate(mm, pud, pmd) \
|
||||
@@ -60,23 +63,40 @@
|
||||
|
||||
#define set_pud(pudptr, pudval) (*(pudptr) = (pudval))
|
||||
|
||||
static inline int pgd_newpage(pgd_t pgd)
|
||||
#define p4d_none(x) (!(p4d_val(x) & ~_PAGE_NEEDSYNC))
|
||||
#define p4d_bad(x) ((p4d_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
|
||||
#define p4d_present(x) (p4d_val(x) & _PAGE_PRESENT)
|
||||
#define p4d_populate(mm, p4d, pud) \
|
||||
set_p4d(p4d, __p4d(_PAGE_TABLE + __pa(pud)))
|
||||
|
||||
#define set_p4d(p4dptr, p4dval) (*(p4dptr) = (p4dval))
|
||||
|
||||
|
||||
static inline int pgd_needsync(pgd_t pgd)
|
||||
{
|
||||
return(pgd_val(pgd) & _PAGE_NEWPAGE);
|
||||
return pgd_val(pgd) & _PAGE_NEEDSYNC;
|
||||
}
|
||||
|
||||
static inline void pgd_mkuptodate(pgd_t pgd) { pgd_val(pgd) &= ~_PAGE_NEWPAGE; }
|
||||
static inline void pgd_mkuptodate(pgd_t pgd) { pgd_val(pgd) &= ~_PAGE_NEEDSYNC; }
|
||||
|
||||
#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
|
||||
|
||||
static inline void pud_clear (pud_t *pud)
|
||||
{
|
||||
set_pud(pud, __pud(_PAGE_NEWPAGE));
|
||||
set_pud(pud, __pud(_PAGE_NEEDSYNC));
|
||||
}
|
||||
|
||||
static inline void p4d_clear (p4d_t *p4d)
|
||||
{
|
||||
set_p4d(p4d, __p4d(_PAGE_NEEDSYNC));
|
||||
}
|
||||
|
||||
#define pud_page(pud) phys_to_page(pud_val(pud) & PAGE_MASK)
|
||||
#define pud_pgtable(pud) ((pmd_t *) __va(pud_val(pud) & PAGE_MASK))
|
||||
|
||||
#define p4d_page(p4d) phys_to_page(p4d_val(p4d) & PAGE_MASK)
|
||||
#define p4d_pgtable(p4d) ((pud_t *) __va(p4d_val(p4d) & PAGE_MASK))
|
||||
|
||||
static inline unsigned long pte_pfn(pte_t pte)
|
||||
{
|
||||
return phys_to_pfn(pte_val(pte));
|
||||
@@ -97,4 +117,3 @@ static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
#include <asm/fixmap.h>
|
||||
|
||||
#define _PAGE_PRESENT 0x001
|
||||
#define _PAGE_NEWPAGE 0x002
|
||||
#define _PAGE_NEWPROT 0x004
|
||||
#define _PAGE_NEEDSYNC 0x002
|
||||
#define _PAGE_RW 0x020
|
||||
#define _PAGE_USER 0x040
|
||||
#define _PAGE_ACCESSED 0x080
|
||||
@@ -24,10 +23,12 @@
|
||||
/* We borrow bit 10 to store the exclusive marker in swap PTEs. */
|
||||
#define _PAGE_SWP_EXCLUSIVE 0x400
|
||||
|
||||
#ifdef CONFIG_3_LEVEL_PGTABLES
|
||||
#include <asm/pgtable-3level.h>
|
||||
#else
|
||||
#if CONFIG_PGTABLE_LEVELS == 4
|
||||
#include <asm/pgtable-4level.h>
|
||||
#elif CONFIG_PGTABLE_LEVELS == 2
|
||||
#include <asm/pgtable-2level.h>
|
||||
#else
|
||||
#error "Unsupported number of page table levels"
|
||||
#endif
|
||||
|
||||
extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
|
||||
@@ -78,22 +79,22 @@ extern unsigned long end_iomem;
|
||||
*/
|
||||
#define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page)
|
||||
|
||||
#define pte_clear(mm,addr,xp) pte_set_val(*(xp), (phys_t) 0, __pgprot(_PAGE_NEWPAGE))
|
||||
#define pte_clear(mm, addr, xp) pte_set_val(*(xp), (phys_t) 0, __pgprot(_PAGE_NEEDSYNC))
|
||||
|
||||
#define pmd_none(x) (!((unsigned long)pmd_val(x) & ~_PAGE_NEWPAGE))
|
||||
#define pmd_none(x) (!((unsigned long)pmd_val(x) & ~_PAGE_NEEDSYNC))
|
||||
#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
|
||||
|
||||
#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
|
||||
#define pmd_clear(xp) do { pmd_val(*(xp)) = _PAGE_NEWPAGE; } while (0)
|
||||
#define pmd_clear(xp) do { pmd_val(*(xp)) = _PAGE_NEEDSYNC; } while (0)
|
||||
|
||||
#define pmd_newpage(x) (pmd_val(x) & _PAGE_NEWPAGE)
|
||||
#define pmd_mkuptodate(x) (pmd_val(x) &= ~_PAGE_NEWPAGE)
|
||||
#define pmd_needsync(x) (pmd_val(x) & _PAGE_NEEDSYNC)
|
||||
#define pmd_mkuptodate(x) (pmd_val(x) &= ~_PAGE_NEEDSYNC)
|
||||
|
||||
#define pud_newpage(x) (pud_val(x) & _PAGE_NEWPAGE)
|
||||
#define pud_mkuptodate(x) (pud_val(x) &= ~_PAGE_NEWPAGE)
|
||||
#define pud_needsync(x) (pud_val(x) & _PAGE_NEEDSYNC)
|
||||
#define pud_mkuptodate(x) (pud_val(x) &= ~_PAGE_NEEDSYNC)
|
||||
|
||||
#define p4d_newpage(x) (p4d_val(x) & _PAGE_NEWPAGE)
|
||||
#define p4d_mkuptodate(x) (p4d_val(x) &= ~_PAGE_NEWPAGE)
|
||||
#define p4d_needsync(x) (p4d_val(x) & _PAGE_NEEDSYNC)
|
||||
#define p4d_mkuptodate(x) (p4d_val(x) &= ~_PAGE_NEEDSYNC)
|
||||
|
||||
#define pmd_pfn(pmd) (pmd_val(pmd) >> PAGE_SHIFT)
|
||||
#define pmd_page(pmd) phys_to_page(pmd_val(pmd) & PAGE_MASK)
|
||||
@@ -144,14 +145,9 @@ static inline int pte_young(pte_t pte)
|
||||
return pte_get_bits(pte, _PAGE_ACCESSED);
|
||||
}
|
||||
|
||||
static inline int pte_newpage(pte_t pte)
|
||||
static inline int pte_needsync(pte_t pte)
|
||||
{
|
||||
return pte_get_bits(pte, _PAGE_NEWPAGE);
|
||||
}
|
||||
|
||||
static inline int pte_newprot(pte_t pte)
|
||||
{
|
||||
return(pte_present(pte) && (pte_get_bits(pte, _PAGE_NEWPROT)));
|
||||
return pte_get_bits(pte, _PAGE_NEEDSYNC);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -160,12 +156,6 @@ static inline int pte_newprot(pte_t pte)
|
||||
* =================================
|
||||
*/
|
||||
|
||||
static inline pte_t pte_mknewprot(pte_t pte)
|
||||
{
|
||||
pte_set_bits(pte, _PAGE_NEWPROT);
|
||||
return(pte);
|
||||
}
|
||||
|
||||
static inline pte_t pte_mkclean(pte_t pte)
|
||||
{
|
||||
pte_clear_bits(pte, _PAGE_DIRTY);
|
||||
@@ -180,19 +170,14 @@ static inline pte_t pte_mkold(pte_t pte)
|
||||
|
||||
static inline pte_t pte_wrprotect(pte_t pte)
|
||||
{
|
||||
if (likely(pte_get_bits(pte, _PAGE_RW)))
|
||||
pte_clear_bits(pte, _PAGE_RW);
|
||||
else
|
||||
return pte;
|
||||
return(pte_mknewprot(pte));
|
||||
pte_clear_bits(pte, _PAGE_RW);
|
||||
return 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);
|
||||
return(pte_mknewprot(pte));
|
||||
return pte;
|
||||
}
|
||||
|
||||
static inline pte_t pte_mkdirty(pte_t pte)
|
||||
@@ -209,23 +194,19 @@ static inline pte_t pte_mkyoung(pte_t pte)
|
||||
|
||||
static inline pte_t pte_mkwrite_novma(pte_t pte)
|
||||
{
|
||||
if (unlikely(pte_get_bits(pte, _PAGE_RW)))
|
||||
return pte;
|
||||
pte_set_bits(pte, _PAGE_RW);
|
||||
return(pte_mknewprot(pte));
|
||||
return pte;
|
||||
}
|
||||
|
||||
static inline pte_t pte_mkuptodate(pte_t pte)
|
||||
{
|
||||
pte_clear_bits(pte, _PAGE_NEWPAGE);
|
||||
if(pte_present(pte))
|
||||
pte_clear_bits(pte, _PAGE_NEWPROT);
|
||||
return(pte);
|
||||
pte_clear_bits(pte, _PAGE_NEEDSYNC);
|
||||
return pte;
|
||||
}
|
||||
|
||||
static inline pte_t pte_mknewpage(pte_t pte)
|
||||
static inline pte_t pte_mkneedsync(pte_t pte)
|
||||
{
|
||||
pte_set_bits(pte, _PAGE_NEWPAGE);
|
||||
pte_set_bits(pte, _PAGE_NEEDSYNC);
|
||||
return(pte);
|
||||
}
|
||||
|
||||
@@ -233,13 +214,11 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
|
||||
{
|
||||
pte_copy(*pteptr, pteval);
|
||||
|
||||
/* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so
|
||||
* fix_range knows to unmap it. _PAGE_NEWPROT is specific to
|
||||
* mapped pages.
|
||||
/* If it's a swap entry, it needs to be marked _PAGE_NEEDSYNC so
|
||||
* update_pte_range knows to unmap it.
|
||||
*/
|
||||
|
||||
*pteptr = pte_mknewpage(*pteptr);
|
||||
if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr);
|
||||
*pteptr = pte_mkneedsync(*pteptr);
|
||||
}
|
||||
|
||||
#define PFN_PTE_SHIFT PAGE_SHIFT
|
||||
@@ -279,7 +258,7 @@ static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
|
||||
#define __HAVE_ARCH_PTE_SAME
|
||||
static inline int pte_same(pte_t pte_a, pte_t pte_b)
|
||||
{
|
||||
return !((pte_val(pte_a) ^ pte_val(pte_b)) & ~_PAGE_NEWPAGE);
|
||||
return !((pte_val(pte_a) ^ pte_val(pte_b)) & ~_PAGE_NEEDSYNC);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -294,8 +273,6 @@ static inline int pte_same(pte_t pte_a, pte_t pte_b)
|
||||
({ pte_t pte; \
|
||||
\
|
||||
pte_set_val(pte, page_to_phys(page), (pgprot)); \
|
||||
if (pte_present(pte)) \
|
||||
pte_mknewprot(pte_mknewpage(pte)); \
|
||||
pte;})
|
||||
|
||||
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
||||
@@ -329,7 +306,7 @@ extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr);
|
||||
* <--------------- offset ----------------> E < type -> 0 0 0 1 0
|
||||
*
|
||||
* E is the exclusive marker that is not stored in swap entries.
|
||||
* _PAGE_NEWPAGE (bit 1) is always set to 1 in set_pte().
|
||||
* _PAGE_NEEDSYNC (bit 1) is always set to 1 in set_pte().
|
||||
*/
|
||||
#define __swp_type(x) (((x).val >> 5) & 0x1f)
|
||||
#define __swp_offset(x) ((x).val >> 11)
|
||||
|
||||
@@ -20,10 +20,7 @@ struct task_struct;
|
||||
struct mm_struct;
|
||||
|
||||
struct thread_struct {
|
||||
struct pt_regs regs;
|
||||
struct pt_regs *segv_regs;
|
||||
void *fault_addr;
|
||||
jmp_buf *fault_catcher;
|
||||
struct task_struct *prev_sched;
|
||||
struct arch_thread arch;
|
||||
jmp_buf switch_buf;
|
||||
@@ -33,12 +30,14 @@ struct thread_struct {
|
||||
void *arg;
|
||||
} thread;
|
||||
} request;
|
||||
|
||||
/* Contains variable sized FP registers */
|
||||
struct pt_regs regs;
|
||||
};
|
||||
|
||||
#define INIT_THREAD \
|
||||
{ \
|
||||
.regs = EMPTY_REGS, \
|
||||
.fault_addr = NULL, \
|
||||
.prev_sched = NULL, \
|
||||
.arch = INIT_ARCH_THREAD, \
|
||||
.request = { } \
|
||||
|
||||
@@ -17,35 +17,17 @@
|
||||
#include <sysdep/ptrace_user.h>
|
||||
|
||||
struct thread_info {
|
||||
struct task_struct *task; /* main task structure */
|
||||
unsigned long flags; /* low level flags */
|
||||
__u32 cpu; /* current CPU */
|
||||
int preempt_count; /* 0 => preemptable,
|
||||
<0 => BUG */
|
||||
struct thread_info *real_thread; /* Points to non-IRQ stack */
|
||||
unsigned long aux_fp_regs[FP_SIZE]; /* auxiliary fp_regs to save/restore
|
||||
them out-of-band */
|
||||
};
|
||||
|
||||
#define INIT_THREAD_INFO(tsk) \
|
||||
{ \
|
||||
.task = &tsk, \
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.real_thread = NULL, \
|
||||
}
|
||||
|
||||
/* how to get the thread information struct from C */
|
||||
static inline struct thread_info *current_thread_info(void)
|
||||
{
|
||||
struct thread_info *ti;
|
||||
unsigned long mask = THREAD_SIZE - 1;
|
||||
void *p;
|
||||
|
||||
asm volatile ("" : "=r" (p) : "0" (&ti));
|
||||
ti = (struct thread_info *) (((unsigned long)p) & ~mask);
|
||||
return ti;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user