This pull request contains the following changes for UML:
- Improve support for non-glibc systems - Vector: Add support for scripting and dynamic tap devices - Various fixes for the vector networking driver - Various fixes for time travel mode -----BEGIN PGP SIGNATURE----- iQJKBAABCAA0FiEEdgfidid8lnn52cLTZvlZhesYu8EFAl+JksYWHHJpY2hhcmRA c2lnbWEtc3Rhci5hdAAKCRBm+VmF6xi7wcUyEAC8CF5NEymDBr5ABptOwnA3GVlR 4ed/Iy1h1pGnM24/2B16te+YWVNUNXyN5GJ8F16Z3nsgB9ehQmHktmcJ76gC9A1s AQOF9qHiomzdkS0d9DFAveEfSs72zH2ypCDeqiDFLsmYH+fYSkVVuilCBryIngrL AsXbM9x9rAL+o7+A1yBmsxLYcqJkikUBiQuP8uXGmRRx8eqZrpmVnkqzDkeNnMqW rmmYv5AQreApA1C3zgs9qVGXBJD8OGTMKPsqnWvydFhsW9jmXGY6MUD5DHayO6xM 7Ws7fkhF0LG68UbGTGnCW2mXEsOxeUuJaFPDw8MMxslImU34ZO/0OHui+KBzvJmk tmL+GvHpKzyT7tsv9Kpyr957cXM1oIG1yfLVLhPG7t3f9fxG3X/gebXIUYPQNyWv IEnE4EoF+BY+Zuds3llJPiFYuNW4J25HTpu1+ILCbOPlkDQ98TUekzKzwHEY2XZg ORP4mTDV4jemYmfFFJdUBmPZ6OjaCWH1+t7ws68Ne/0h32aIDagYj+B8ubgJBH5S GH4/mxxQ4AlfmTSbU47wxuKDhv6mEMyOKIMTyDXqpYgDloI/g9IKj1Pfz+RN6qbb LVssoJI+lr0L9NPDnVZ2BNoTCDhryMfctOUkfCA0RWXdnygQWVbyizbx56VK78NJ ZPcGjo3BOxg9TRRDNQ== =OzDf -----END PGP SIGNATURE----- Merge tag 'for-linus-5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml Pull UML updates from Richard Weinberger: - Improve support for non-glibc systems - Vector: Add support for scripting and dynamic tap devices - Various fixes for the vector networking driver - Various fixes for time travel mode * tag 'for-linus-5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml: um: vector: Add dynamic tap interfaces and scripting um: Clean up stacktrace dump um: Fix incorrect assumptions about max pid length um: Remove dead usage of TIF_IA32 um: Remove redundant NULL check um: change sigio_spinlock to a mutex um: time-travel: Return the sequence number in ACK messages um: time-travel: Fix IRQ handling in time_travel_handle_message() um: Allow static linking for non-glibc implementations um: Some fixes to build UML with musl um: vector: Use GFP_ATOMIC under spin lock um: Fix null pointer dereference in vector_user_bpf
This commit is contained in:
Коммит
9453b2d469
|
@ -62,12 +62,12 @@ config NR_CPUS
|
||||||
|
|
||||||
source "arch/$(HEADER_ARCH)/um/Kconfig"
|
source "arch/$(HEADER_ARCH)/um/Kconfig"
|
||||||
|
|
||||||
config FORBID_STATIC_LINK
|
config MAY_HAVE_RUNTIME_DEPS
|
||||||
bool
|
bool
|
||||||
|
|
||||||
config STATIC_LINK
|
config STATIC_LINK
|
||||||
bool "Force a static link"
|
bool "Force a static link"
|
||||||
depends on !FORBID_STATIC_LINK
|
depends on CC_CAN_LINK_STATIC_NO_RUNTIME_DEPS || !MAY_HAVE_RUNTIME_DEPS
|
||||||
help
|
help
|
||||||
This option gives you the ability to force a static link of UML.
|
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
|
Normally, UML is linked as a shared binary. This is inconvenient for
|
||||||
|
|
|
@ -234,7 +234,7 @@ config UML_NET_DAEMON
|
||||||
config UML_NET_VECTOR
|
config UML_NET_VECTOR
|
||||||
bool "Vector I/O high performance network devices"
|
bool "Vector I/O high performance network devices"
|
||||||
depends on UML_NET
|
depends on UML_NET
|
||||||
select FORBID_STATIC_LINK
|
select MAY_HAVE_RUNTIME_DEPS
|
||||||
help
|
help
|
||||||
This User-Mode Linux network driver uses multi-message send
|
This User-Mode Linux network driver uses multi-message send
|
||||||
and receive functions. The host running the UML guest must have
|
and receive functions. The host running the UML guest must have
|
||||||
|
@ -246,7 +246,7 @@ config UML_NET_VECTOR
|
||||||
config UML_NET_VDE
|
config UML_NET_VDE
|
||||||
bool "VDE transport (obsolete)"
|
bool "VDE transport (obsolete)"
|
||||||
depends on UML_NET
|
depends on UML_NET
|
||||||
select FORBID_STATIC_LINK
|
select MAY_HAVE_RUNTIME_DEPS
|
||||||
help
|
help
|
||||||
This User-Mode Linux network transport allows one or more running
|
This User-Mode Linux network transport allows one or more running
|
||||||
UMLs on a single host to communicate with each other and also
|
UMLs on a single host to communicate with each other and also
|
||||||
|
@ -294,7 +294,7 @@ config UML_NET_MCAST
|
||||||
config UML_NET_PCAP
|
config UML_NET_PCAP
|
||||||
bool "pcap transport (obsolete)"
|
bool "pcap transport (obsolete)"
|
||||||
depends on UML_NET
|
depends on UML_NET
|
||||||
select FORBID_STATIC_LINK
|
select MAY_HAVE_RUNTIME_DEPS
|
||||||
help
|
help
|
||||||
The pcap transport makes a pcap packet stream on the host look
|
The pcap transport makes a pcap packet stream on the host look
|
||||||
like an ethernet device inside UML. This is useful for making
|
like an ethernet device inside UML. This is useful for making
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
|
@ -32,7 +32,7 @@ static int pcap_user_init(void *data, void *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcap_open(void *data)
|
static int pcap_user_open(void *data)
|
||||||
{
|
{
|
||||||
struct pcap_data *pri = data;
|
struct pcap_data *pri = data;
|
||||||
__u32 netmask;
|
__u32 netmask;
|
||||||
|
@ -44,14 +44,14 @@ static int pcap_open(void *data)
|
||||||
if (pri->filter != NULL) {
|
if (pri->filter != NULL) {
|
||||||
err = dev_netmask(pri->dev, &netmask);
|
err = dev_netmask(pri->dev, &netmask);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
printk(UM_KERN_ERR "pcap_open : dev_netmask failed\n");
|
printk(UM_KERN_ERR "pcap_user_open : dev_netmask failed\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
pri->compiled = uml_kmalloc(sizeof(struct bpf_program),
|
pri->compiled = uml_kmalloc(sizeof(struct bpf_program),
|
||||||
UM_GFP_KERNEL);
|
UM_GFP_KERNEL);
|
||||||
if (pri->compiled == NULL) {
|
if (pri->compiled == NULL) {
|
||||||
printk(UM_KERN_ERR "pcap_open : kmalloc failed\n");
|
printk(UM_KERN_ERR "pcap_user_open : kmalloc failed\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,14 +59,14 @@ static int pcap_open(void *data)
|
||||||
(struct bpf_program *) pri->compiled,
|
(struct bpf_program *) pri->compiled,
|
||||||
pri->filter, pri->optimize, netmask);
|
pri->filter, pri->optimize, netmask);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
printk(UM_KERN_ERR "pcap_open : pcap_compile failed - "
|
printk(UM_KERN_ERR "pcap_user_open : pcap_compile failed - "
|
||||||
"'%s'\n", pcap_geterr(pri->pcap));
|
"'%s'\n", pcap_geterr(pri->pcap));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = pcap_setfilter(pri->pcap, pri->compiled);
|
err = pcap_setfilter(pri->pcap, pri->compiled);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
printk(UM_KERN_ERR "pcap_open : pcap_setfilter "
|
printk(UM_KERN_ERR "pcap_user_open : pcap_setfilter "
|
||||||
"failed - '%s'\n", pcap_geterr(pri->pcap));
|
"failed - '%s'\n", pcap_geterr(pri->pcap));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri)
|
||||||
|
|
||||||
const struct net_user_info pcap_user_info = {
|
const struct net_user_info pcap_user_info = {
|
||||||
.init = pcap_user_init,
|
.init = pcap_user_init,
|
||||||
.open = pcap_open,
|
.open = pcap_user_open,
|
||||||
.close = NULL,
|
.close = NULL,
|
||||||
.remove = pcap_remove,
|
.remove = pcap_remove,
|
||||||
.add_address = NULL,
|
.add_address = NULL,
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/termios.h>
|
#include <termios.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <net_user.h>
|
#include <net_user.h>
|
||||||
#include <os.h>
|
#include <os.h>
|
||||||
|
|
|
@ -1403,7 +1403,7 @@ static int vector_net_load_bpf_flash(struct net_device *dev,
|
||||||
kfree(vp->bpf->filter);
|
kfree(vp->bpf->filter);
|
||||||
vp->bpf->filter = NULL;
|
vp->bpf->filter = NULL;
|
||||||
} else {
|
} else {
|
||||||
vp->bpf = kmalloc(sizeof(struct sock_fprog), GFP_KERNEL);
|
vp->bpf = kmalloc(sizeof(struct sock_fprog), GFP_ATOMIC);
|
||||||
if (vp->bpf == NULL) {
|
if (vp->bpf == NULL) {
|
||||||
netdev_err(dev, "failed to allocate memory for firmware\n");
|
netdev_err(dev, "failed to allocate memory for firmware\n");
|
||||||
goto flash_fail;
|
goto flash_fail;
|
||||||
|
@ -1415,7 +1415,7 @@ static int vector_net_load_bpf_flash(struct net_device *dev,
|
||||||
if (request_firmware(&fw, efl->data, &vdevice->pdev.dev))
|
if (request_firmware(&fw, efl->data, &vdevice->pdev.dev))
|
||||||
goto flash_fail;
|
goto flash_fail;
|
||||||
|
|
||||||
vp->bpf->filter = kmemdup(fw->data, fw->size, GFP_KERNEL);
|
vp->bpf->filter = kmemdup(fw->data, fw->size, GFP_ATOMIC);
|
||||||
if (!vp->bpf->filter)
|
if (!vp->bpf->filter)
|
||||||
goto free_buffer;
|
goto free_buffer;
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <net/ethernet.h>
|
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
#include <netinet/ether.h>
|
|
||||||
#include <linux/if_ether.h>
|
#include <linux/if_ether.h>
|
||||||
#include <linux/if_packet.h>
|
#include <linux/if_packet.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
@ -39,6 +37,7 @@
|
||||||
#define ID_MAX 2
|
#define ID_MAX 2
|
||||||
|
|
||||||
#define TOKEN_IFNAME "ifname"
|
#define TOKEN_IFNAME "ifname"
|
||||||
|
#define TOKEN_SCRIPT "ifup"
|
||||||
|
|
||||||
#define TRANS_RAW "raw"
|
#define TRANS_RAW "raw"
|
||||||
#define TRANS_RAW_LEN strlen(TRANS_RAW)
|
#define TRANS_RAW_LEN strlen(TRANS_RAW)
|
||||||
|
@ -55,6 +54,9 @@
|
||||||
|
|
||||||
#define MAX_UN_LEN 107
|
#define MAX_UN_LEN 107
|
||||||
|
|
||||||
|
static const char padchar[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
static const char *template = "tapXXXXXX";
|
||||||
|
|
||||||
/* This is very ugly and brute force lookup, but it is done
|
/* This is very ugly and brute force lookup, but it is done
|
||||||
* only once at initialization so not worth doing hashes or
|
* only once at initialization so not worth doing hashes or
|
||||||
* anything more intelligent
|
* anything more intelligent
|
||||||
|
@ -191,16 +193,21 @@ raw_fd_cleanup:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct vector_fds *user_init_tap_fds(struct arglist *ifspec)
|
static struct vector_fds *user_init_tap_fds(struct arglist *ifspec)
|
||||||
{
|
{
|
||||||
int fd = -1;
|
int fd = -1, i;
|
||||||
char *iface;
|
char *iface;
|
||||||
struct vector_fds *result = NULL;
|
struct vector_fds *result = NULL;
|
||||||
|
bool dynamic = false;
|
||||||
|
char dynamic_ifname[IFNAMSIZ];
|
||||||
|
char *argv[] = {NULL, NULL, NULL, NULL};
|
||||||
|
|
||||||
iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME);
|
iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME);
|
||||||
if (iface == NULL) {
|
if (iface == NULL) {
|
||||||
printk(UM_KERN_ERR "uml_tap: failed to parse interface spec\n");
|
dynamic = true;
|
||||||
goto tap_cleanup;
|
iface = dynamic_ifname;
|
||||||
|
srand(getpid());
|
||||||
}
|
}
|
||||||
|
|
||||||
result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
|
result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
|
||||||
|
@ -214,14 +221,30 @@ static struct vector_fds *user_init_tap_fds(struct arglist *ifspec)
|
||||||
result->remote_addr_size = 0;
|
result->remote_addr_size = 0;
|
||||||
|
|
||||||
/* TAP */
|
/* TAP */
|
||||||
|
do {
|
||||||
|
if (dynamic) {
|
||||||
|
strcpy(iface, template);
|
||||||
|
for (i = 0; i < strlen(iface); i++) {
|
||||||
|
if (iface[i] == 'X') {
|
||||||
|
iface[i] = padchar[rand() % strlen(padchar)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fd = create_tap_fd(iface);
|
||||||
|
if ((fd < 0) && (!dynamic)) {
|
||||||
|
printk(UM_KERN_ERR "uml_tap: failed to create tun interface\n");
|
||||||
|
goto tap_cleanup;
|
||||||
|
}
|
||||||
|
result->tx_fd = fd;
|
||||||
|
result->rx_fd = fd;
|
||||||
|
} while (fd < 0);
|
||||||
|
|
||||||
fd = create_tap_fd(iface);
|
argv[0] = uml_vector_fetch_arg(ifspec, TOKEN_SCRIPT);
|
||||||
if (fd < 0) {
|
if (argv[0]) {
|
||||||
printk(UM_KERN_ERR "uml_tap: failed to create tun interface\n");
|
argv[1] = iface;
|
||||||
goto tap_cleanup;
|
run_helper(NULL, NULL, argv);
|
||||||
}
|
}
|
||||||
result->tx_fd = fd;
|
|
||||||
result->rx_fd = fd;
|
|
||||||
return result;
|
return result;
|
||||||
tap_cleanup:
|
tap_cleanup:
|
||||||
printk(UM_KERN_ERR "user_init_tap: init failed, error %d", fd);
|
printk(UM_KERN_ERR "user_init_tap: init failed, error %d", fd);
|
||||||
|
@ -233,6 +256,7 @@ static struct vector_fds *user_init_hybrid_fds(struct arglist *ifspec)
|
||||||
{
|
{
|
||||||
char *iface;
|
char *iface;
|
||||||
struct vector_fds *result = NULL;
|
struct vector_fds *result = NULL;
|
||||||
|
char *argv[] = {NULL, NULL, NULL, NULL};
|
||||||
|
|
||||||
iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME);
|
iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME);
|
||||||
if (iface == NULL) {
|
if (iface == NULL) {
|
||||||
|
@ -266,6 +290,12 @@ static struct vector_fds *user_init_hybrid_fds(struct arglist *ifspec)
|
||||||
"uml_tap: failed to create paired raw socket: %i\n", result->rx_fd);
|
"uml_tap: failed to create paired raw socket: %i\n", result->rx_fd);
|
||||||
goto hybrid_cleanup;
|
goto hybrid_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
argv[0] = uml_vector_fetch_arg(ifspec, TOKEN_SCRIPT);
|
||||||
|
if (argv[0]) {
|
||||||
|
argv[1] = iface;
|
||||||
|
run_helper(NULL, NULL, argv);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
hybrid_cleanup:
|
hybrid_cleanup:
|
||||||
printk(UM_KERN_ERR "user_init_hybrid: init failed");
|
printk(UM_KERN_ERR "user_init_hybrid: init failed");
|
||||||
|
@ -332,7 +362,7 @@ static struct vector_fds *user_init_unix_fds(struct arglist *ifspec, int id)
|
||||||
}
|
}
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case ID_BESS:
|
case ID_BESS:
|
||||||
if (connect(fd, remote_addr, sizeof(struct sockaddr_un)) < 0) {
|
if (connect(fd, (const struct sockaddr *) remote_addr, sizeof(struct sockaddr_un)) < 0) {
|
||||||
printk(UM_KERN_ERR "bess open:cannot connect to %s %i", remote_addr->sun_path, -errno);
|
printk(UM_KERN_ERR "bess open:cannot connect to %s %i", remote_addr->sun_path, -errno);
|
||||||
goto unix_cleanup;
|
goto unix_cleanup;
|
||||||
}
|
}
|
||||||
|
@ -399,8 +429,7 @@ static struct vector_fds *user_init_fd_fds(struct arglist *ifspec)
|
||||||
fd_cleanup:
|
fd_cleanup:
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
os_close_file(fd);
|
os_close_file(fd);
|
||||||
if (result != NULL)
|
kfree(result);
|
||||||
kfree(result);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,6 +439,7 @@ static struct vector_fds *user_init_raw_fds(struct arglist *ifspec)
|
||||||
int err = -ENOMEM;
|
int err = -ENOMEM;
|
||||||
char *iface;
|
char *iface;
|
||||||
struct vector_fds *result = NULL;
|
struct vector_fds *result = NULL;
|
||||||
|
char *argv[] = {NULL, NULL, NULL, NULL};
|
||||||
|
|
||||||
iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME);
|
iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME);
|
||||||
if (iface == NULL)
|
if (iface == NULL)
|
||||||
|
@ -432,6 +462,11 @@ static struct vector_fds *user_init_raw_fds(struct arglist *ifspec)
|
||||||
result->remote_addr = NULL;
|
result->remote_addr = NULL;
|
||||||
result->remote_addr_size = 0;
|
result->remote_addr_size = 0;
|
||||||
}
|
}
|
||||||
|
argv[0] = uml_vector_fetch_arg(ifspec, TOKEN_SCRIPT);
|
||||||
|
if (argv[0]) {
|
||||||
|
argv[1] = iface;
|
||||||
|
run_helper(NULL, NULL, argv);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
raw_cleanup:
|
raw_cleanup:
|
||||||
printk(UM_KERN_ERR "user_init_raw: init failed, error %d", err);
|
printk(UM_KERN_ERR "user_init_raw: init failed, error %d", err);
|
||||||
|
@ -789,10 +824,12 @@ void *uml_vector_user_bpf(char *filename)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bpf_prog = uml_kmalloc(sizeof(struct sock_fprog), UM_GFP_KERNEL);
|
bpf_prog = uml_kmalloc(sizeof(struct sock_fprog), UM_GFP_KERNEL);
|
||||||
if (bpf_prog != NULL) {
|
if (bpf_prog == NULL) {
|
||||||
bpf_prog->len = statbuf.st_size / sizeof(struct sock_filter);
|
printk(KERN_ERR "Failed to allocate bpf prog buffer");
|
||||||
bpf_prog->filter = NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
bpf_prog->len = statbuf.st_size / sizeof(struct sock_filter);
|
||||||
|
bpf_prog->filter = NULL;
|
||||||
ffd = os_open_file(filename, of_read(OPENFLAGS()), 0);
|
ffd = os_open_file(filename, of_read(OPENFLAGS()), 0);
|
||||||
if (ffd < 0) {
|
if (ffd < 0) {
|
||||||
printk(KERN_ERR "Error %d opening bpf file", -errno);
|
printk(KERN_ERR "Error %d opening bpf file", -errno);
|
||||||
|
|
|
@ -35,14 +35,14 @@ int write_sigio_irq(int fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These are called from os-Linux/sigio.c to protect its pollfds arrays. */
|
/* These are called from os-Linux/sigio.c to protect its pollfds arrays. */
|
||||||
static DEFINE_SPINLOCK(sigio_spinlock);
|
static DEFINE_MUTEX(sigio_mutex);
|
||||||
|
|
||||||
void sigio_lock(void)
|
void sigio_lock(void)
|
||||||
{
|
{
|
||||||
spin_lock(&sigio_spinlock);
|
mutex_lock(&sigio_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sigio_unlock(void)
|
void sigio_unlock(void)
|
||||||
{
|
{
|
||||||
spin_unlock(&sigio_spinlock);
|
mutex_unlock(&sigio_mutex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,12 +47,10 @@ void show_stack(struct task_struct *task, unsigned long *stack,
|
||||||
if (kstack_end(stack))
|
if (kstack_end(stack))
|
||||||
break;
|
break;
|
||||||
if (i && ((i % STACKSLOTS_PER_LINE) == 0))
|
if (i && ((i % STACKSLOTS_PER_LINE) == 0))
|
||||||
printk("%s\n", loglvl);
|
pr_cont("\n");
|
||||||
pr_cont(" %08lx", *stack++);
|
pr_cont(" %08lx", *stack++);
|
||||||
}
|
}
|
||||||
printk("%s\n", loglvl);
|
|
||||||
|
|
||||||
printk("%sCall Trace:\n", loglvl);
|
printk("%sCall Trace:\n", loglvl);
|
||||||
dump_trace(current, &stackops, (void *)loglvl);
|
dump_trace(current, &stackops, (void *)loglvl);
|
||||||
printk("%s\n", loglvl);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,13 +70,17 @@ static void time_travel_handle_message(struct um_timetravel_msg *msg,
|
||||||
* read of the message and write of the ACK.
|
* read of the message and write of the ACK.
|
||||||
*/
|
*/
|
||||||
if (mode != TTMH_READ) {
|
if (mode != TTMH_READ) {
|
||||||
|
bool disabled = irqs_disabled();
|
||||||
|
|
||||||
|
BUG_ON(mode == TTMH_IDLE && !disabled);
|
||||||
|
|
||||||
|
if (disabled)
|
||||||
|
local_irq_enable();
|
||||||
while (os_poll(1, &time_travel_ext_fd) != 0) {
|
while (os_poll(1, &time_travel_ext_fd) != 0) {
|
||||||
if (mode == TTMH_IDLE) {
|
/* nothing */
|
||||||
BUG_ON(!irqs_disabled());
|
|
||||||
local_irq_enable();
|
|
||||||
local_irq_disable();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (disabled)
|
||||||
|
local_irq_disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = os_read_file(time_travel_ext_fd, msg, sizeof(*msg));
|
ret = os_read_file(time_travel_ext_fd, msg, sizeof(*msg));
|
||||||
|
@ -102,6 +106,7 @@ static void time_travel_handle_message(struct um_timetravel_msg *msg,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resp.seq = msg->seq;
|
||||||
os_write_file(time_travel_ext_fd, &resp, sizeof(resp));
|
os_write_file(time_travel_ext_fd, &resp, sizeof(resp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ static int remove_files_and_dir(char *dir)
|
||||||
while ((ent = readdir(directory)) != NULL) {
|
while ((ent = readdir(directory)) != NULL) {
|
||||||
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
|
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
|
||||||
continue;
|
continue;
|
||||||
len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1;
|
len = strlen(dir) + strlen("/") + strlen(ent->d_name) + 1;
|
||||||
if (len > sizeof(file)) {
|
if (len > sizeof(file)) {
|
||||||
ret = -E2BIG;
|
ret = -E2BIG;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -135,7 +135,7 @@ out:
|
||||||
*/
|
*/
|
||||||
static inline int is_umdir_used(char *dir)
|
static inline int is_umdir_used(char *dir)
|
||||||
{
|
{
|
||||||
char pid[sizeof("nnnnn\0")], *end, *file;
|
char pid[sizeof("nnnnnnnnn")], *end, *file;
|
||||||
int dead, fd, p, n, err;
|
int dead, fd, p, n, err;
|
||||||
size_t filelen;
|
size_t filelen;
|
||||||
|
|
||||||
|
@ -217,10 +217,10 @@ static int umdir_take_if_dead(char *dir)
|
||||||
|
|
||||||
static void __init create_pid_file(void)
|
static void __init create_pid_file(void)
|
||||||
{
|
{
|
||||||
char pid[sizeof("nnnnn\0")], *file;
|
char pid[sizeof("nnnnnnnnn")], *file;
|
||||||
int fd, n;
|
int fd, n;
|
||||||
|
|
||||||
n = strlen(uml_dir) + UMID_LEN + sizeof("/pid\0");
|
n = strlen(uml_dir) + UMID_LEN + sizeof("/pid");
|
||||||
file = malloc(n);
|
file = malloc(n);
|
||||||
if (!file)
|
if (!file)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
|
|
|
@ -52,14 +52,6 @@ static const int reg_offsets[] =
|
||||||
|
|
||||||
int putreg(struct task_struct *child, int regno, unsigned long value)
|
int putreg(struct task_struct *child, int regno, unsigned long value)
|
||||||
{
|
{
|
||||||
#ifdef TIF_IA32
|
|
||||||
/*
|
|
||||||
* Some code in the 64bit emulation may not be 64bit clean.
|
|
||||||
* Don't take any chances.
|
|
||||||
*/
|
|
||||||
if (test_tsk_thread_flag(child, TIF_IA32))
|
|
||||||
value &= 0xffffffff;
|
|
||||||
#endif
|
|
||||||
switch (regno) {
|
switch (regno) {
|
||||||
case R8:
|
case R8:
|
||||||
case R9:
|
case R9:
|
||||||
|
@ -137,10 +129,7 @@ int poke_user(struct task_struct *child, long addr, long data)
|
||||||
unsigned long getreg(struct task_struct *child, int regno)
|
unsigned long getreg(struct task_struct *child, int regno)
|
||||||
{
|
{
|
||||||
unsigned long mask = ~0UL;
|
unsigned long mask = ~0UL;
|
||||||
#ifdef TIF_IA32
|
|
||||||
if (test_tsk_thread_flag(child, TIF_IA32))
|
|
||||||
mask = 0xffffffff;
|
|
||||||
#endif
|
|
||||||
switch (regno) {
|
switch (regno) {
|
||||||
case R8:
|
case R8:
|
||||||
case R9:
|
case R9:
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/poll.h>
|
#include <poll.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/user.h>
|
#include <sys/user.h>
|
||||||
#define __FRAME_OFFSETS
|
#define __FRAME_OFFSETS
|
||||||
|
|
Загрузка…
Ссылка в новой задаче