diff options
| author | Al Viro <viro@ftp.linux.org.uk> | 2006-10-24 06:15:29 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-25 01:01:10 -0400 |
| commit | 3a51237dc11efe283b40ea0248f4e26ab935dbd1 (patch) | |
| tree | d27f5f2cbaea27119914186650739f281f796e77 | |
| parent | 6c50444723f2e6487b3377450f90d813a88e6c31 (diff) | |
[PATCH] uml: mconsole fixes
* when we have stop/sysrq/go, we get pt_regs of whatever executes
mc_work_proc(). Would be better to see what we had at the time of
interrupt that got us stop.
* stop/stop/stop..... will give stack overflow. Shouldn't allow stop
from mconsole_stop().
* stop/stop/go leaves us inside mconsole_stop() with
os_set_fd_block(req->originating_fd, 0);
reactivate_fd(req->originating_fd, MCONSOLE_IRQ);
just done by nested mconsole_stop(). Ditto.
* once we'd seen stop, there's a period when INTR commands are executed
out of order (as they should; we might have the things stuck badly
enough to never reach mconsole_stop(), but still not badly enough to
block mconsole_interrupt(); in that situation we _want_ things like
"cad" to be executed immediately). Once we enter monsole_stop(), all
INTR commands will be executed in order, mixed with PROC ones. We'd
better let user see that such change of behaviour has happened.
(Suggested by lennert).
* stack footprint of monsole_interrupt() is an atrocity; AFAICS we can
safely make struct mc_request req; static in function there.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | arch/um/drivers/mconsole_kern.c | 23 | ||||
| -rw-r--r-- | arch/um/drivers/mconsole_user.c | 1 | ||||
| -rw-r--r-- | arch/um/include/mconsole.h | 1 |
3 files changed, 19 insertions, 6 deletions
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index d08bd036ccb8..7b172160fe04 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c | |||
| @@ -79,7 +79,7 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id) | |||
| 79 | /* long to avoid size mismatch warnings from gcc */ | 79 | /* long to avoid size mismatch warnings from gcc */ |
| 80 | long fd; | 80 | long fd; |
| 81 | struct mconsole_entry *new; | 81 | struct mconsole_entry *new; |
| 82 | struct mc_request req; | 82 | static struct mc_request req; /* that's OK */ |
| 83 | 83 | ||
| 84 | fd = (long) dev_id; | 84 | fd = (long) dev_id; |
| 85 | while (mconsole_get_request(fd, &req)){ | 85 | while (mconsole_get_request(fd, &req)){ |
| @@ -91,6 +91,7 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id) | |||
| 91 | mconsole_reply(&req, "Out of memory", 1, 0); | 91 | mconsole_reply(&req, "Out of memory", 1, 0); |
| 92 | else { | 92 | else { |
| 93 | new->request = req; | 93 | new->request = req; |
| 94 | new->request.regs = get_irq_regs()->regs; | ||
| 94 | list_add(&new->list, &mc_requests); | 95 | list_add(&new->list, &mc_requests); |
| 95 | } | 96 | } |
| 96 | } | 97 | } |
| @@ -314,9 +315,21 @@ void mconsole_stop(struct mc_request *req) | |||
| 314 | { | 315 | { |
| 315 | deactivate_fd(req->originating_fd, MCONSOLE_IRQ); | 316 | deactivate_fd(req->originating_fd, MCONSOLE_IRQ); |
| 316 | os_set_fd_block(req->originating_fd, 1); | 317 | os_set_fd_block(req->originating_fd, 1); |
| 317 | mconsole_reply(req, "", 0, 0); | 318 | mconsole_reply(req, "stopped", 0, 0); |
| 318 | while(mconsole_get_request(req->originating_fd, req)){ | 319 | while (mconsole_get_request(req->originating_fd, req)) { |
| 319 | if(req->cmd->handler == mconsole_go) break; | 320 | if (req->cmd->handler == mconsole_go) |
| 321 | break; | ||
| 322 | if (req->cmd->handler == mconsole_stop) { | ||
| 323 | mconsole_reply(req, "Already stopped", 1, 0); | ||
| 324 | continue; | ||
| 325 | } | ||
| 326 | if (req->cmd->handler == mconsole_sysrq) { | ||
| 327 | struct pt_regs *old_regs; | ||
| 328 | old_regs = set_irq_regs((struct pt_regs *)&req->regs); | ||
| 329 | mconsole_sysrq(req); | ||
| 330 | set_irq_regs(old_regs); | ||
| 331 | continue; | ||
| 332 | } | ||
| 320 | (*req->cmd->handler)(req); | 333 | (*req->cmd->handler)(req); |
| 321 | } | 334 | } |
| 322 | os_set_fd_block(req->originating_fd, 0); | 335 | os_set_fd_block(req->originating_fd, 0); |
| @@ -673,9 +686,7 @@ static void with_console(struct mc_request *req, void (*proc)(void *), | |||
| 673 | static void sysrq_proc(void *arg) | 686 | static void sysrq_proc(void *arg) |
| 674 | { | 687 | { |
| 675 | char *op = arg; | 688 | char *op = arg; |
| 676 | struct pt_regs *old_regs = set_irq_regs(¤t->thread.regs); | ||
| 677 | handle_sysrq(*op, NULL); | 689 | handle_sysrq(*op, NULL); |
| 678 | set_irq_regs(old_regs); | ||
| 679 | } | 690 | } |
| 680 | 691 | ||
| 681 | void mconsole_sysrq(struct mc_request *req) | 692 | void mconsole_sysrq(struct mc_request *req) |
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index 17068eb746c0..75aef6f7ef6e 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <sys/un.h> | 14 | #include <sys/un.h> |
| 15 | #include <unistd.h> | 15 | #include <unistd.h> |
| 16 | #include "user.h" | 16 | #include "user.h" |
| 17 | #include "sysdep/ptrace.h" | ||
| 17 | #include "mconsole.h" | 18 | #include "mconsole.h" |
| 18 | #include "umid.h" | 19 | #include "umid.h" |
| 19 | #include "user_util.h" | 20 | #include "user_util.h" |
diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h index 58f67d391105..2666815b6af5 100644 --- a/arch/um/include/mconsole.h +++ b/arch/um/include/mconsole.h | |||
| @@ -61,6 +61,7 @@ struct mc_request | |||
| 61 | 61 | ||
| 62 | struct mconsole_request request; | 62 | struct mconsole_request request; |
| 63 | struct mconsole_command *cmd; | 63 | struct mconsole_command *cmd; |
| 64 | union uml_pt_regs regs; | ||
| 64 | }; | 65 | }; |
| 65 | 66 | ||
| 66 | extern char mconsole_socket_name[]; | 67 | extern char mconsole_socket_name[]; |
