Pull UML fixes from Richard Weinberger: "This patch set contains mostly fixes and cleanups. The UML tty driver uses now tty_port and is no longer broken like hell :-)" * 'for-linus-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml: um: Add arch/x86/um to MAINTAINERS um: pass siginfo to guest process um: fix ubd_file_size for read-only files um: pull interrupt_end() into userspace() um: split syscall_trace(), pass pt_regs to it um: switch UPT_SET_RETURN_VALUE and regs_return_value to pt_regs um: set BLK_CGROUP=y in defconfig um: remove count_lock um: fully use tty_port um: Remove dead code um: remove line_ioctl() TTY: um/line, use tty from tty_port TTY: um/line, add tty_port
Unified · Split
| @@ -7382,6 +7382,7 @@ W: http://user-mode-linux.sourceforge.net · 7381 unmodified lines | ||
| 7382 | 7382 | S: Maintained |
| 7383 | 7383 | F: Documentation/virtual/uml/ |
| 7384 | 7384 | F: arch/um/ |
| 7385 | +F: arch/x86/um/ | |
| 7385 | 7386 | F: fs/hostfs/ |
| 7386 | 7387 | F: fs/hppfs/ |
| 7387 | 7388 | |
| @@ -163,7 +163,7 @@ CONFIG_CGROUP_SCHED=y · 162 unmodified lines | ||
| 163 | 163 | CONFIG_FAIR_GROUP_SCHED=y |
| 164 | 164 | # CONFIG_CFS_BANDWIDTH is not set |
| 165 | 165 | # CONFIG_RT_GROUP_SCHED is not set |
| 166 | −CONFIG_BLK_CGROUP=m | |
| 166 | +CONFIG_BLK_CGROUP=y | |
| 167 | 167 | # CONFIG_DEBUG_BLK_CGROUP is not set |
| 168 | 168 | # CONFIG_CHECKPOINT_RESTORE is not set |
| 169 | 169 | CONFIG_NAMESPACES=y |
| @@ -150,9 +150,11 @@ void chan_enable_winch(struct chan *chan, struct tty_struct *tty) · 149 unmodified lines | ||
| 150 | 150 | static void line_timer_cb(struct work_struct *work) |
| 151 | 151 | { |
| 152 | 152 | struct line *line = container_of(work, struct line, task.work); |
| 153 | + struct tty_struct *tty = tty_port_tty_get(&line->port); | |
| 153 | 154 | |
| 154 | 155 | if (!line->throttled) |
| 155 | − chan_interrupt(line, line->tty, line->driver->read_irq); | |
| 156 | + chan_interrupt(line, tty, line->driver->read_irq); | |
| 157 | + tty_kref_put(tty); | |
| 156 | 158 | } |
| 157 | 159 | |
| 158 | 160 | int enable_chan(struct line *line) |
| @@ -19,9 +19,11 @@ static irqreturn_t line_interrupt(int irq, void *data) · 18 unmodified lines | ||
| 19 | 19 | { |
| 20 | 20 | struct chan *chan = data; |
| 21 | 21 | struct line *line = chan->line; |
| 22 | + struct tty_struct *tty = tty_port_tty_get(&line->port); | |
| 22 | 23 | |
| 23 | 24 | if (line) |
| 24 | − chan_interrupt(line, line->tty, irq); | |
| 25 | + chan_interrupt(line, tty, irq); | |
| 26 | + tty_kref_put(tty); | |
| 25 | 27 | return IRQ_HANDLED; |
| 26 | 28 | } |
| 27 | 29 | |
| @@ -219,92 +221,6 @@ void line_set_termios(struct tty_struct *tty, struct ktermios * old) · 191 unmodified lines | ||
| 219 | 221 | /* nothing */ |
| 220 | 222 | } |
| 221 | 223 | |
| 222 | −static const struct { | |
| 223 | − int cmd; | |
| 224 | − char *level; | |
| 225 | − char *name; | |
| 226 | −} tty_ioctls[] = { | |
| 227 | − /* don't print these, they flood the log ... */ | |
| 228 | − { TCGETS, NULL, "TCGETS" }, | |
| 229 | − { TCSETS, NULL, "TCSETS" }, | |
| 230 | − { TCSETSW, NULL, "TCSETSW" }, | |
| 231 | − { TCFLSH, NULL, "TCFLSH" }, | |
| 232 | − { TCSBRK, NULL, "TCSBRK" }, | |
| 233 | − | |
| 234 | − /* general tty stuff */ | |
| 235 | − { TCSETSF, KERN_DEBUG, "TCSETSF" }, | |
| 236 | − { TCGETA, KERN_DEBUG, "TCGETA" }, | |
| 237 | − { TIOCMGET, KERN_DEBUG, "TIOCMGET" }, | |
| 238 | − { TCSBRKP, KERN_DEBUG, "TCSBRKP" }, | |
| 239 | − { TIOCMSET, KERN_DEBUG, "TIOCMSET" }, | |
| 240 | − | |
| 241 | − /* linux-specific ones */ | |
| 242 | − { TIOCLINUX, KERN_INFO, "TIOCLINUX" }, | |
| 243 | − { KDGKBMODE, KERN_INFO, "KDGKBMODE" }, | |
| 244 | − { KDGKBTYPE, KERN_INFO, "KDGKBTYPE" }, | |
| 245 | − { KDSIGACCEPT, KERN_INFO, "KDSIGACCEPT" }, | |
| 246 | −}; | |
| 247 | − | |
| 248 | −int line_ioctl(struct tty_struct *tty, unsigned int cmd, | |
| 249 | − unsigned long arg) | |
| 250 | −{ | |
| 251 | − int ret; | |
| 252 | − int i; | |
| 253 | − | |
| 254 | − ret = 0; | |
| 255 | − switch(cmd) { | |
| 256 | −#ifdef TIOCGETP | |
| 257 | − case TIOCGETP: | |
| 258 | − case TIOCSETP: | |
| 259 | − case TIOCSETN: | |
| 260 | −#endif | |
| 261 | −#ifdef TIOCGETC | |
| 262 | − case TIOCGETC: | |
| 263 | − case TIOCSETC: | |
| 264 | −#endif | |
| 265 | −#ifdef TIOCGLTC | |
| 266 | − case TIOCGLTC: | |
| 267 | − case TIOCSLTC: | |
| 268 | −#endif | |
| 269 | − /* Note: these are out of date as we now have TCGETS2 etc but this | |
| 270 | − whole lot should probably go away */ | |
| 271 | − case TCGETS: | |
| 272 | − case TCSETSF: | |
| 273 | − case TCSETSW: | |
| 274 | − case TCSETS: | |
| 275 | − case TCGETA: | |
| 276 | − case TCSETAF: | |
| 277 | − case TCSETAW: | |
| 278 | − case TCSETA: | |
| 279 | − case TCXONC: | |
| 280 | − case TCFLSH: | |
| 281 | − case TIOCOUTQ: | |
| 282 | − case TIOCINQ: | |
| 283 | − case TIOCGLCKTRMIOS: | |
| 284 | − case TIOCSLCKTRMIOS: | |
| 285 | − case TIOCPKT: | |
| 286 | − case TIOCGSOFTCAR: | |
| 287 | − case TIOCSSOFTCAR: | |
| 288 | − return -ENOIOCTLCMD; | |
| 289 | −#if 0 | |
| 290 | − case TCwhatever: | |
| 291 | − /* do something */ | |
| 292 | − break; | |
| 293 | −#endif | |
| 294 | − default: | |
| 295 | − for (i = 0; i < ARRAY_SIZE(tty_ioctls); i++) | |
| 296 | − if (cmd == tty_ioctls[i].cmd) | |
| 297 | − break; | |
| 298 | − if (i == ARRAY_SIZE(tty_ioctls)) { | |
| 299 | − printk(KERN_ERR "%s: %s: unknown ioctl: 0x%x\n", | |
| 300 | − __func__, tty->name, cmd); | |
| 301 | − } | |
| 302 | − ret = -ENOIOCTLCMD; | |
| 303 | − break; | |
| 304 | − } | |
| 305 | − return ret; | |
| 306 | −} | |
| 307 | − | |
| 308 | 224 | void line_throttle(struct tty_struct *tty) |
| 309 | 225 | { |
| 310 | 226 | struct line *line = tty->driver_data; |
| @@ -333,7 +249,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data) · 22 unmodified lines | ||
| 333 | 249 | { |
| 334 | 250 | struct chan *chan = data; |
| 335 | 251 | struct line *line = chan->line; |
| 336 | − struct tty_struct *tty = line->tty; | |
| 252 | + struct tty_struct *tty; | |
| 337 | 253 | int err; |
| 338 | 254 | |
| 339 | 255 | /* |
| @@ -352,10 +268,13 @@ static irqreturn_t line_write_interrupt(int irq, void *data) · 12 unmodified lines | ||
| 352 | 268 | } |
| 353 | 269 | spin_unlock(&line->lock); |
| 354 | 270 | |
| 271 | + tty = tty_port_tty_get(&line->port); | |
| 355 | 272 | if (tty == NULL) |
| 356 | 273 | return IRQ_NONE; |
| 357 | 274 | |
| 358 | 275 | tty_wakeup(tty); |
| 276 | + tty_kref_put(tty); | |
| 277 | + | |
| 359 | 278 | return IRQ_HANDLED; |
| 360 | 279 | } |
| 361 | 280 | |
| @@ -377,43 +296,14 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data) · 15 unmodified lines | ||
| 377 | 296 | return err; |
| 378 | 297 | } |
| 379 | 298 | |
| 380 | −/* | |
| 381 | − * Normally, a driver like this can rely mostly on the tty layer | |
| 382 | − * locking, particularly when it comes to the driver structure. | |
| 383 | − * However, in this case, mconsole requests can come in "from the | |
| 384 | − * side", and race with opens and closes. | |
| 385 | − * | |
| 386 | − * mconsole config requests will want to be sure the device isn't in | |
| 387 | − * use, and get_config, open, and close will want a stable | |
| 388 | − * configuration. The checking and modification of the configuration | |
| 389 | − * is done under a spinlock. Checking whether the device is in use is | |
| 390 | − * line->tty->count > 1, also under the spinlock. | |
| 391 | − * | |
| 392 | − * line->count serves to decide whether the device should be enabled or | |
| 393 | − * disabled on the host. If it's equal to 0, then we are doing the | |
| 394 | − * first open or last close. Otherwise, open and close just return. | |
| 395 | − */ | |
| 396 | − | |
| 397 | −int line_open(struct line *lines, struct tty_struct *tty) | |
| 299 | +static int line_activate(struct tty_port *port, struct tty_struct *tty) | |
| 398 | 300 | { |
| 399 | − struct line *line = &lines[tty->index]; | |
| 400 | − int err = -ENODEV; | |
| 401 | − | |
| 402 | − mutex_lock(&line->count_lock); | |
| 403 | − if (!line->valid) | |
| 404 | − goto out_unlock; | |
| 405 | − | |
| 406 | − err = 0; | |
| 407 | − if (line->count++) | |
| 408 | − goto out_unlock; | |
| 409 | − | |
| 410 | − BUG_ON(tty->driver_data); | |
| 411 | − tty->driver_data = line; | |
| 412 | − line->tty = tty; | |
| 301 | + int ret; | |
| 302 | + struct line *line = tty->driver_data; | |
| 413 | 303 | |
| 414 | − err = enable_chan(line); | |
| 415 | − if (err) /* line_close() will be called by our caller */ | |
| 416 | − goto out_unlock; | |
| 304 | + ret = enable_chan(line); | |
| 305 | + if (ret) | |
| 306 | + return ret; | |
| 417 | 307 | |
| 418 | 308 | if (!line->sigio) { |
| 419 | 309 | chan_enable_winch(line->chan_out, tty); |
| @@ -421,44 +311,60 @@ int line_open(struct line *lines, struct tty_struct *tty) · 1 unmodified line | ||
| 421 | 311 | } |
| 422 | 312 | |
| 423 | 313 | chan_window_size(line, &tty->winsize.ws_row, |
| 424 | − &tty->winsize.ws_col); | |
| 425 | −out_unlock: | |
| 426 | − mutex_unlock(&line->count_lock); | |
| 427 | − return err; | |
| 314 | + &tty->winsize.ws_col); | |
| 315 | + | |
| 316 | + return 0; | |
| 428 | 317 | } |
| 429 | 318 | |
| 430 | −static void unregister_winch(struct tty_struct *tty); | |
| 319 | +static const struct tty_port_operations line_port_ops = { | |
| 320 | + .activate = line_activate, | |
| 321 | +}; | |
| 431 | 322 | |
| 432 | −void line_close(struct tty_struct *tty, struct file * filp) | |
| 323 | +int line_open(struct tty_struct *tty, struct file *filp) | |
| 433 | 324 | { |
| 434 | 325 | struct line *line = tty->driver_data; |
| 435 | 326 | |
| 436 | − /* | |
| 437 | − * If line_open fails (and tty->driver_data is never set), | |
| 438 | − * tty_open will call line_close. So just return in this case. | |
| 439 | − */ | |
| 440 | − if (line == NULL) | |
| 441 | − return; | |
| 327 | + return tty_port_open(&line->port, tty, filp); | |
| 328 | +} | |
| 442 | 329 | |
| 443 | − /* We ignore the error anyway! */ | |
| 444 | − flush_buffer(line); | |
| 330 | +int line_install(struct tty_driver *driver, struct tty_struct *tty, | |
| 331 | + struct line *line) | |
| 332 | +{ | |
| 333 | + int ret; | |
| 445 | 334 | |
| 446 | − mutex_lock(&line->count_lock); | |
| 447 | − BUG_ON(!line->valid); | |
| 335 | + ret = tty_standard_install(driver, tty); | |
| 336 | + if (ret) | |
| 337 | + return ret; | |
| 448 | 338 | |
| 449 | − if (--line->count) | |
| 450 | − goto out_unlock; | |
| 339 | + tty->driver_data = line; | |
| 451 | 340 | |
| 452 | − line->tty = NULL; | |
| 453 | − tty->driver_data = NULL; | |
| 341 | + return 0; | |
| 342 | +} | |
| 343 | + | |
| 344 | +static void unregister_winch(struct tty_struct *tty); | |
| 345 | + | |
| 346 | +void line_cleanup(struct tty_struct *tty) | |
| 347 | +{ | |
| 348 | + struct line *line = tty->driver_data; | |
| 454 | 349 | |
| 455 | 350 | if (line->sigio) { |
| 456 | 351 | unregister_winch(tty); |
| 457 | 352 | line->sigio = 0; |
| 458 | 353 | } |
| 354 | +} | |
| 355 | + | |
| 356 | +void line_close(struct tty_struct *tty, struct file * filp) | |
| 357 | +{ | |
| 358 | + struct line *line = tty->driver_data; | |
| 459 | 359 | |
| 460 | −out_unlock: | |
| 461 | − mutex_unlock(&line->count_lock); | |
| 360 | + tty_port_close(&line->port, tty, filp); | |
| 361 | +} | |
| 362 | + | |
| 363 | +void line_hangup(struct tty_struct *tty) | |
| 364 | +{ | |
| 365 | + struct line *line = tty->driver_data; | |
| 366 | + | |
| 367 | + tty_port_hangup(&line->port); | |
| 462 | 368 | } |
| 463 | 369 | |
| 464 | 370 | void close_lines(struct line *lines, int nlines) |
| @@ -476,9 +382,7 @@ int setup_one_line(struct line *lines, int n, char *init, · 11 unmodified lines | ||
| 476 | 382 | struct tty_driver *driver = line->driver->driver; |
| 477 | 383 | int err = -EINVAL; |
| 478 | 384 | |
| 479 | − mutex_lock(&line->count_lock); | |
| 480 | − | |
| 481 | − if (line->count) { | |
| 385 | + if (line->port.count) { | |
| 482 | 386 | *error_out = "Device is already open"; |
| 483 | 387 | goto out; |
| 484 | 388 | } |
| @@ -519,7 +423,6 @@ int setup_one_line(struct line *lines, int n, char *init, · 34 unmodified lines | ||
| 519 | 423 | } |
| 520 | 424 | } |
| 521 | 425 | out: |
| 522 | − mutex_unlock(&line->count_lock); | |
| 523 | 426 | return err; |
| 524 | 427 | } |
| 525 | 428 | |
| @@ -607,13 +510,17 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, · 81 unmodified lines | ||
| 607 | 510 | |
| 608 | 511 | line = &lines[dev]; |
| 609 | 512 | |
| 610 | − mutex_lock(&line->count_lock); | |
| 611 | 513 | if (!line->valid) |
| 612 | 514 | CONFIG_CHUNK(str, size, n, "none", 1); |
| 613 | − else if (line->tty == NULL) | |
| 614 | − CONFIG_CHUNK(str, size, n, line->init_str, 1); | |
| 615 | − else n = chan_config_string(line, str, size, error_out); | |
| 616 | − mutex_unlock(&line->count_lock); | |
| 515 | + else { | |
| 516 | + struct tty_struct *tty = tty_port_tty_get(&line->port); | |
| 517 | + if (tty == NULL) { | |
| 518 | + CONFIG_CHUNK(str, size, n, line->init_str, 1); | |
| 519 | + } else { | |
| 520 | + n = chan_config_string(line, str, size, error_out); | |
| 521 | + tty_kref_put(tty); | |
| 522 | + } | |
| 523 | + } | |
| 617 | 524 | |
| 618 | 525 | return n; |
| 619 | 526 | } |
| @@ -663,8 +570,9 @@ int register_lines(struct line_driver *line_driver, · 43 unmodified lines | ||
| 663 | 570 | driver->init_termios = tty_std_termios; |
| 664 | 571 | |
| 665 | 572 | for (i = 0; i < nlines; i++) { |
| 573 | + tty_port_init(&lines[i].port); | |
| 574 | + lines[i].port.ops = &line_port_ops; | |
| 666 | 575 | spin_lock_init(&lines[i].lock); |
| 667 | − mutex_init(&lines[i].count_lock); | |
| 668 | 576 | lines[i].driver = line_driver; |
| 669 | 577 | INIT_LIST_HEAD(&lines[i].chan_list); |
| 670 | 578 | } |
| @@ -32,9 +32,7 @@ struct line_driver { · 31 unmodified lines | ||
| 32 | 32 | }; |
| 33 | 33 | |
| 34 | 34 | struct line { |
| 35 | − struct tty_struct *tty; | |
| 36 | − struct mutex count_lock; | |
| 37 | − unsigned long count; | |
| 35 | + struct tty_port port; | |
| 38 | 36 | int valid; |
| 39 | 37 | |
| 40 | 38 | char *init_str; |
| @@ -59,7 +57,11 @@ struct line { · 18 unmodified lines | ||
| 59 | 57 | }; |
| 60 | 58 | |
| 61 | 59 | extern void line_close(struct tty_struct *tty, struct file * filp); |
| 62 | −extern int line_open(struct line *lines, struct tty_struct *tty); | |
| 60 | +extern int line_open(struct tty_struct *tty, struct file *filp); | |
| 61 | +extern int line_install(struct tty_driver *driver, struct tty_struct *tty, | |
| 62 | + struct line *line); | |
| 63 | +extern void line_cleanup(struct tty_struct *tty); | |
| 64 | +extern void line_hangup(struct tty_struct *tty); | |
| 63 | 65 | extern int line_setup(char **conf, unsigned nlines, char **def, |
| 64 | 66 | char *init, char *name); |
| 65 | 67 | extern int line_write(struct tty_struct *tty, const unsigned char *buf, |
| @@ -70,8 +72,6 @@ extern int line_chars_in_buffer(struct tty_struct *tty); · 4 unmodified lines | ||
| 70 | 72 | extern void line_flush_buffer(struct tty_struct *tty); |
| 71 | 73 | extern void line_flush_chars(struct tty_struct *tty); |
| 72 | 74 | extern int line_write_room(struct tty_struct *tty); |
| 73 | −extern int line_ioctl(struct tty_struct *tty, unsigned int cmd, | |
| 74 | − unsigned long arg); | |
| 75 | 75 | extern void line_throttle(struct tty_struct *tty); |
| 76 | 76 | extern void line_unthrottle(struct tty_struct *tty); |
| 77 | 77 | |
| @@ -87,40 +87,13 @@ static int ssl_remove(int n, char **error_out) · 86 unmodified lines | ||
| 87 | 87 | error_out); |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | −static int ssl_open(struct tty_struct *tty, struct file *filp) | |
| 91 | −{ | |
| 92 | − int err = line_open(serial_lines, tty); | |
| 93 | − | |
| 94 | − if (err) | |
| 95 | − printk(KERN_ERR "Failed to open serial line %d, err = %d\n", | |
| 96 | − tty->index, err); | |
| 97 | − | |
| 98 | − return err; | |
| 99 | −} | |
| 100 | − | |
| 101 | −#if 0 | |
| 102 | −static void ssl_flush_buffer(struct tty_struct *tty) | |
| 103 | −{ | |
| 104 | − return; | |
| 105 | −} | |
| 106 | − | |
| 107 | −static void ssl_stop(struct tty_struct *tty) | |
| 108 | −{ | |
| 109 | − printk(KERN_ERR "Someone should implement ssl_stop\n"); | |
| 110 | −} | |
| 111 | − | |
| 112 | −static void ssl_start(struct tty_struct *tty) | |
| 113 | −{ | |
| 114 | − printk(KERN_ERR "Someone should implement ssl_start\n"); | |
| 115 | −} | |
| 116 | − | |
| 117 | −void ssl_hangup(struct tty_struct *tty) | |
| 90 | +static int ssl_install(struct tty_driver *driver, struct tty_struct *tty) | |
| 118 | 91 | { |
| 92 | + return line_install(driver, tty, &serial_lines[tty->index]); | |
| 119 | 93 | } |
| 120 | −#endif | |
| 121 | 94 | |
| 122 | 95 | static const struct tty_operations ssl_ops = { |
| 123 | − .open = ssl_open, | |
| 96 | + .open = line_open, | |
| 124 | 97 | .close = line_close, |
| 125 | 98 | .write = line_write, |
| 126 | 99 | .put_char = line_put_char, |
| @@ -129,14 +102,11 @@ static const struct tty_operations ssl_ops = { · 2 unmodified lines | ||
| 129 | 102 | .flush_buffer = line_flush_buffer, |
| 130 | 103 | .flush_chars = line_flush_chars, |
| 131 | 104 | .set_termios = line_set_termios, |
| 132 | − .ioctl = line_ioctl, | |
| 133 | 105 | .throttle = line_throttle, |
| 134 | 106 | .unthrottle = line_unthrottle, |
| 135 | −#if 0 | |
| 136 | − .stop = ssl_stop, | |
| 137 | − .start = ssl_start, | |
| 138 | − .hangup = ssl_hangup, | |
| 139 | −#endif | |
| 107 | + .install = ssl_install, | |
| 108 | + .cleanup = line_cleanup, | |
| 109 | + .hangup = line_hangup, | |
| 140 | 110 | }; |
| 141 | 111 | |
| 142 | 112 | /* Changed by ssl_init and referenced by ssl_exit, which are both serialized |
| @@ -89,21 +89,17 @@ static int con_remove(int n, char **error_out) · 88 unmodified lines | ||
| 89 | 89 | return line_remove(vts, ARRAY_SIZE(vts), n, error_out); |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | −static int con_open(struct tty_struct *tty, struct file *filp) | |
| 93 | −{ | |
| 94 | − int err = line_open(vts, tty); | |
| 95 | − if (err) | |
| 96 | − printk(KERN_ERR "Failed to open console %d, err = %d\n", | |
| 97 | − tty->index, err); | |
| 98 | − | |
| 99 | − return err; | |
| 100 | −} | |
| 101 | − | |
| 102 | 92 | /* Set in an initcall, checked in an exitcall */ |
| 103 | 93 | static int con_init_done = 0; |
| 104 | 94 | |
| 95 | +static int con_install(struct tty_driver *driver, struct tty_struct *tty) | |
| 96 | +{ | |
| 97 | + return line_install(driver, tty, &vts[tty->index]); | |
| 98 | +} | |
| 99 | + | |
| 105 | 100 | static const struct tty_operations console_ops = { |
| 106 | − .open = con_open, | |
| 101 | + .open = line_open, | |
| 102 | + .install = con_install, | |
| 107 | 103 | .close = line_close, |
| 108 | 104 | .write = line_write, |
| 109 | 105 | .put_char = line_put_char, |
| @@ -112,9 +108,10 @@ static const struct tty_operations console_ops = { · 2 unmodified lines | ||
| 112 | 108 | .flush_buffer = line_flush_buffer, |
| 113 | 109 | .flush_chars = line_flush_chars, |
| 114 | 110 | .set_termios = line_set_termios, |
| 115 | − .ioctl = line_ioctl, | |
| 116 | 111 | .throttle = line_throttle, |
| 117 | 112 | .unthrottle = line_unthrottle, |
| 113 | + .cleanup = line_cleanup, | |
| 114 | + .hangup = line_hangup, | |
| 118 | 115 | }; |
| 119 | 116 | |
| 120 | 117 | static void uml_console_write(struct console *console, const char *string, |
| @@ -514,7 +514,7 @@ static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out) · 513 unmodified lines | ||
| 514 | 514 | goto out; |
| 515 | 515 | } |
| 516 | 516 | |
| 517 | − fd = os_open_file(ubd_dev->file, global_openflags, 0); | |
| 517 | + fd = os_open_file(ubd_dev->file, of_read(OPENFLAGS()), 0); | |
| 518 | 518 | if (fd < 0) |
| 519 | 519 | return fd; |
| 520 | 520 | |
| @@ -37,6 +37,8 @@ extern int putreg(struct task_struct *child, int regno, unsigned long value); · 36 unmodified lines | ||
| 37 | 37 | |
| 38 | 38 | extern int arch_copy_tls(struct task_struct *new); |
| 39 | 39 | extern void clear_flushed_tls(struct task_struct *task); |
| 40 | +extern void syscall_trace_enter(struct pt_regs *regs); | |
| 41 | +extern void syscall_trace_leave(struct pt_regs *regs); | |
| 40 | 42 | |
| 41 | 43 | #endif |
| 42 | 44 | |
| @@ -60,7 +60,8 @@ extern unsigned long host_task_size; · 59 unmodified lines | ||
| 60 | 60 | |
| 61 | 61 | extern int linux_main(int argc, char **argv); |
| 62 | 62 | |
| 63 | −extern void (*sig_info[])(int, struct uml_pt_regs *); | |
| 63 | +struct siginfo; | |
| 64 | +extern void (*sig_info[])(int, struct siginfo *si, struct uml_pt_regs *); | |
| 64 | 65 | |
| 65 | 66 | #endif |
| 66 | 67 | |
| @@ -20,7 +20,8 @@ struct irq_fd { · 19 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | enum { IRQ_READ, IRQ_WRITE }; |
| 22 | 22 | |
| 23 | −extern void sigio_handler(int sig, struct uml_pt_regs *regs); | |
| 23 | +struct siginfo; | |
| 24 | +extern void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); | |
| 24 | 25 | extern void free_irq_by_fd(int fd); |
| 25 | 26 | extern void reactivate_fd(int fd, int irqnum); |
| 26 | 27 | extern void deactivate_fd(int fd, int irqnum); |
| @@ -9,6 +9,8 @@ · 8 unmodified lines | ||
| 9 | 9 | #include "sysdep/ptrace.h" |
| 10 | 10 | #include "sysdep/faultinfo.h" |
| 11 | 11 | |
| 12 | +struct siginfo; | |
| 13 | + | |
| 12 | 14 | extern int uml_exitcode; |
| 13 | 15 | |
| 14 | 16 | extern int ncpus; |
| @@ -22,7 +24,7 @@ extern void free_stack(unsigned long stack, int order); · 7 unmodified lines | ||
| 22 | 24 | |
| 23 | 25 | extern int do_signal(void); |
| 24 | 26 | extern void interrupt_end(void); |
| 25 | −extern void relay_signal(int sig, struct uml_pt_regs *regs); | |
| 27 | +extern void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs); | |
| 26 | 28 | |
| 27 | 29 | extern unsigned long segv(struct faultinfo fi, unsigned long ip, |
| 28 | 30 | int is_user, struct uml_pt_regs *regs); |
| @@ -33,9 +35,8 @@ extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs); · 4 unmodified lines | ||
| 33 | 35 | extern int smp_sigio_handler(void); |
| 34 | 36 | extern void initial_thread_cb(void (*proc)(void *), void *arg); |
| 35 | 37 | extern int is_syscall(unsigned long addr); |
| 36 | −extern void timer_handler(int sig, struct uml_pt_regs *regs); | |
| 37 | 38 | |
| 38 | −extern void timer_handler(int sig, struct uml_pt_regs *regs); | |
| 39 | +extern void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); | |
| 39 | 40 | |
| 40 | 41 | extern int start_uml(void); |
| 41 | 42 | extern void paging_init(void); |
| @@ -59,9 +60,9 @@ extern unsigned long from_irq_stack(int nested); · 17 unmodified lines | ||
| 59 | 60 | extern void syscall_trace(struct uml_pt_regs *regs, int entryexit); |
| 60 | 61 | extern int singlestepping(void *t); |
| 61 | 62 | |
| 62 | −extern void segv_handler(int sig, struct uml_pt_regs *regs); | |
| 63 | −extern void bus_handler(int sig, struct uml_pt_regs *regs); | |
| 64 | −extern void winch(int sig, struct uml_pt_regs *regs); | |
| 63 | +extern void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); | |
| 64 | +extern void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs); | |
| 65 | +extern void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); | |
| 65 | 66 | extern void fatal_sigsegv(void) __attribute__ ((noreturn)); |
| 66 | 67 | |
| 67 | 68 | |
| @@ -30,7 +30,7 @@ static struct irq_fd **last_irq_ptr = &active_fds; · 29 unmodified lines | ||
| 30 | 30 | |
| 31 | 31 | extern void free_irqs(void); |
| 32 | 32 | |
| 33 | −void sigio_handler(int sig, struct uml_pt_regs *regs) | |
| 33 | +void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) | |
| 34 | 34 | { |
| 35 | 35 | struct irq_fd *irq_fd; |
| 36 | 36 | int n; |
| @@ -151,12 +151,10 @@ void new_thread_handler(void) · 150 unmodified lines | ||
| 151 | 151 | * 0 if it just exits |
| 152 | 152 | */ |
| 153 | 153 | n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); |
| 154 | − if (n == 1) { | |
| 155 | − /* Handle any immediate reschedules or signals */ | |
| 156 | − interrupt_end(); | |
| 154 | + if (n == 1) | |
| 157 | 155 | userspace(¤t->thread.regs.regs); |
| 158 | − } | |
| 159 | − else do_exit(0); | |
| 156 | + else | |
| 157 | + do_exit(0); | |
| 160 | 158 | } |
| 161 | 159 | |
| 162 | 160 | /* Called magically, see new_thread_handler above */ |
| @@ -175,9 +173,6 @@ void fork_handler(void) · 12 unmodified lines | ||
| 175 | 173 | |
| 176 | 174 | current->thread.prev_sched = NULL; |
| 177 | 175 | |
| 178 | − /* Handle any immediate reschedules or signals */ | |
| 179 | − interrupt_end(); | |
| 180 | − | |
| 181 | 176 | userspace(¤t->thread.regs.regs); |
| 182 | 177 | } |
| 183 | 178 | |
| @@ -193,7 +188,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, · 9 unmodified lines | ||
| 193 | 188 | if (current->thread.forking) { |
| 194 | 189 | memcpy(&p->thread.regs.regs, ®s->regs, |
| 195 | 190 | sizeof(p->thread.regs.regs)); |
| 196 | − UPT_SET_SYSCALL_RETURN(&p->thread.regs.regs, 0); | |
| 191 | + PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0); | |
| 197 | 192 | if (sp != 0) |
| 198 | 193 | REGS_SP(p->thread.regs.regs.gp) = sp; |
| 199 | 194 | |
| @@ -3,11 +3,12 @@ · 2 unmodified lines | ||
| 3 | 3 | * Licensed under the GPL |
| 4 | 4 | */ |
| 5 | 5 | |
| 6 | −#include "linux/audit.h" | |
| 7 | −#include "linux/ptrace.h" | |
| 8 | −#include "linux/sched.h" | |
| 9 | −#include "asm/uaccess.h" | |
| 10 | −#include "skas_ptrace.h" | |
| 6 | +#include <linux/audit.h> | |
| 7 | +#include <linux/ptrace.h> | |
| 8 | +#include <linux/sched.h> | |
| 9 | +#include <linux/tracehook.h> | |
| 10 | +#include <asm/uaccess.h> | |
| 11 | +#include <skas_ptrace.h> | |
| 11 | 12 | |
| 12 | 13 | |
| 13 | 14 | |
| @@ -162,48 +163,36 @@ static void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs, · 148 unmodified lines | ||
| 162 | 163 | * XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and |
| 163 | 164 | * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check |
| 164 | 165 | */ |
| 165 | −void syscall_trace(struct uml_pt_regs *regs, int entryexit) | |
| 166 | +void syscall_trace_enter(struct pt_regs *regs) | |
| 166 | 167 | { |
| 167 | − int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit; | |
| 168 | − int tracesysgood; | |
| 169 | − | |
| 170 | − if (!entryexit) | |
| 171 | − audit_syscall_entry(HOST_AUDIT_ARCH, | |
| 172 | − UPT_SYSCALL_NR(regs), | |
| 173 | − UPT_SYSCALL_ARG1(regs), | |
| 174 | − UPT_SYSCALL_ARG2(regs), | |
| 175 | − UPT_SYSCALL_ARG3(regs), | |
| 176 | − UPT_SYSCALL_ARG4(regs)); | |
| 177 | − else | |
| 178 | − audit_syscall_exit(regs); | |
| 179 | − | |
| 180 | − /* Fake a debug trap */ | |
| 181 | − if (is_singlestep) | |
| 182 | − send_sigtrap(current, regs, 0); | |
| 168 | + audit_syscall_entry(HOST_AUDIT_ARCH, | |
| 169 | + UPT_SYSCALL_NR(®s->regs), | |
| 170 | + UPT_SYSCALL_ARG1(®s->regs), | |
| 171 | + UPT_SYSCALL_ARG2(®s->regs), | |
| 172 | + UPT_SYSCALL_ARG3(®s->regs), | |
| 173 | + UPT_SYSCALL_ARG4(®s->regs)); | |
| 183 | 174 | |
| 184 | 175 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) |
| 185 | 176 | return; |
| 186 | 177 | |
| 187 | − if (!(current->ptrace & PT_PTRACED)) | |
| 188 | − return; | |
| 178 | + tracehook_report_syscall_entry(regs); | |
| 179 | +} | |
| 189 | 180 | |
| 190 | − /* | |
| 191 | − * the 0x80 provides a way for the tracing parent to distinguish | |
| 192 | − * between a syscall stop and SIGTRAP delivery | |
| 193 | − */ | |
| 194 | − tracesysgood = (current->ptrace & PT_TRACESYSGOOD); | |
| 195 | − ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0)); | |
| 181 | +void syscall_trace_leave(struct pt_regs *regs) | |
| 182 | +{ | |
| 183 | + int ptraced = current->ptrace; | |
| 196 | 184 | |
| 197 | − if (entryexit) /* force do_signal() --> is_syscall() */ | |
| 198 | − set_thread_flag(TIF_SIGPENDING); | |
| 185 | + audit_syscall_exit(regs); | |
| 199 | 186 | |
| 200 | − /* | |
| 201 | − * this isn't the same as continuing with a signal, but it will do | |
| 202 | − * for normal use. strace only continues with a signal if the | |
| 203 | − * stopping signal is not SIGTRAP. -brl | |
| 204 | − */ | |
| 205 | − if (current->exit_code) { | |
| 206 | − send_sig(current->exit_code, current, 1); | |
| 207 | − current->exit_code = 0; | |
| 208 | − } | |
| 187 | + /* Fake a debug trap */ | |
| 188 | + if (ptraced & PT_DTRACE) | |
| 189 | + send_sigtrap(current, ®s->regs, 0); | |
| 190 | + | |
| 191 | + if (!test_thread_flag(TIF_SYSCALL_TRACE)) | |
| 192 | + return; | |
| 193 | + | |
| 194 | + tracehook_report_syscall_exit(regs, 0); | |
| 195 | + /* force do_signal() --> is_syscall() */ | |
| 196 | + if (ptraced & PT_PTRACED) | |
| 197 | + set_thread_flag(TIF_SIGPENDING); | |
| 209 | 198 | } |
| @@ -18,7 +18,7 @@ void handle_syscall(struct uml_pt_regs *r) · 17 unmodified lines | ||
| 18 | 18 | long result; |
| 19 | 19 | int syscall; |
| 20 | 20 | |
| 21 | − syscall_trace(r, 0); | |
| 21 | + syscall_trace_enter(regs); | |
| 22 | 22 | |
| 23 | 23 | /* |
| 24 | 24 | * This should go in the declaration of syscall, but when I do that, |
| @@ -34,7 +34,7 @@ void handle_syscall(struct uml_pt_regs *r) · 9 unmodified lines | ||
| 34 | 34 | result = -ENOSYS; |
| 35 | 35 | else result = EXECUTE_SYSCALL(syscall, regs); |
| 36 | 36 | |
| 37 | − UPT_SET_SYSCALL_RETURN(r, result); | |
| 37 | + PT_REGS_SET_SYSCALL_RETURN(regs, result); | |
| 38 | 38 | |
| 39 | − syscall_trace(r, 1); | |
| 39 | + syscall_trace_leave(regs); | |
| 40 | 40 | } |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include "kern_util.h" |
| 14 | 14 | #include "os.h" |
| 15 | 15 | |
| 16 | −void timer_handler(int sig, struct uml_pt_regs *regs) | |
| 16 | +void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) | |
| 17 | 17 | { |
| 18 | 18 | unsigned long flags; |
| 19 | 19 | |
| @@ -172,7 +172,7 @@ void fatal_sigsegv(void) · 171 unmodified lines | ||
| 172 | 172 | os_dump_core(); |
| 173 | 173 | } |
| 174 | 174 | |
| 175 | −void segv_handler(int sig, struct uml_pt_regs *regs) | |
| 175 | +void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) | |
| 176 | 176 | { |
| 177 | 177 | struct faultinfo * fi = UPT_FAULTINFO(regs); |
| 178 | 178 | |
| @@ -258,8 +258,11 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, · 79 unmodified lines | ||
| 258 | 258 | return 0; |
| 259 | 259 | } |
| 260 | 260 | |
| 261 | −void relay_signal(int sig, struct uml_pt_regs *regs) | |
| 261 | +void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs) | |
| 262 | 262 | { |
| 263 | + struct faultinfo *fi; | |
| 264 | + struct siginfo clean_si; | |
| 265 | + | |
| 263 | 266 | if (!UPT_IS_USER(regs)) { |
| 264 | 267 | if (sig == SIGBUS) |
| 265 | 268 | printk(KERN_ERR "Bus error - the host /dev/shm or /tmp " |
| @@ -269,18 +272,40 @@ void relay_signal(int sig, struct uml_pt_regs *regs) · 3 unmodified lines | ||
| 269 | 272 | |
| 270 | 273 | arch_examine_signal(sig, regs); |
| 271 | 274 | |
| 272 | − current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); | |
| 273 | − force_sig(sig, current); | |
| 275 | + memset(&clean_si, 0, sizeof(clean_si)); | |
| 276 | + clean_si.si_signo = si->si_signo; | |
| 277 | + clean_si.si_errno = si->si_errno; | |
| 278 | + clean_si.si_code = si->si_code; | |
| 279 | + switch (sig) { | |
| 280 | + case SIGILL: | |
| 281 | + case SIGFPE: | |
| 282 | + case SIGSEGV: | |
| 283 | + case SIGBUS: | |
| 284 | + case SIGTRAP: | |
| 285 | + fi = UPT_FAULTINFO(regs); | |
| 286 | + clean_si.si_addr = (void __user *) FAULT_ADDRESS(*fi); | |
| 287 | + current->thread.arch.faultinfo = *fi; | |
| 288 | +#ifdef __ARCH_SI_TRAPNO | |
| 289 | + clean_si.si_trapno = si->si_trapno; | |
| 290 | +#endif | |
| 291 | + break; | |
| 292 | + default: | |
| 293 | + printk(KERN_ERR "Attempted to relay unknown signal %d (si_code = %d)\n", | |
| 294 | + sig, si->si_code); | |
| 295 | + } | |
| 296 | + | |
| 297 | + force_sig_info(sig, &clean_si, current); | |
| 274 | 298 | } |
| 275 | 299 | |
| 276 | −void bus_handler(int sig, struct uml_pt_regs *regs) | |
| 300 | +void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs) | |
| 277 | 301 | { |
| 278 | 302 | if (current->thread.fault_catcher != NULL) |
| 279 | 303 | UML_LONGJMP(current->thread.fault_catcher, 1); |
| 280 | − else relay_signal(sig, regs); | |
| 304 | + else | |
| 305 | + relay_signal(sig, si, regs); | |
| 281 | 306 | } |
| 282 | 307 | |
| 283 | −void winch(int sig, struct uml_pt_regs *regs) | |
| 308 | +void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) | |
| 284 | 309 | { |
| 285 | 310 | do_IRQ(WINCH_IRQ, regs); |
| 286 | 311 | } |
| @@ -1 +1 @@ | ||
| 1 | −void alarm_handler(int, mcontext_t *); | |
| 1 | +void alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc); | |
| @@ -13,8 +13,9 @@ · 12 unmodified lines | ||
| 13 | 13 | #include "kern_util.h" |
| 14 | 14 | #include "os.h" |
| 15 | 15 | #include "sysdep/mcontext.h" |
| 16 | +#include "internal.h" | |
| 16 | 17 | |
| 17 | −void (*sig_info[NSIG])(int, struct uml_pt_regs *) = { | |
| 18 | +void (*sig_info[NSIG])(int, siginfo_t *, struct uml_pt_regs *) = { | |
| 18 | 19 | [SIGTRAP] = relay_signal, |
| 19 | 20 | [SIGFPE] = relay_signal, |
| 20 | 21 | [SIGILL] = relay_signal, |
| @@ -24,7 +25,7 @@ void (*sig_info[NSIG])(int, struct uml_pt_regs *) = { · 3 unmodified lines | ||
| 24 | 25 | [SIGIO] = sigio_handler, |
| 25 | 26 | [SIGVTALRM] = timer_handler }; |
| 26 | 27 | |
| 27 | −static void sig_handler_common(int sig, mcontext_t *mc) | |
| 28 | +static void sig_handler_common(int sig, siginfo_t *si, mcontext_t *mc) | |
| 28 | 29 | { |
| 29 | 30 | struct uml_pt_regs r; |
| 30 | 31 | int save_errno = errno; |
| @@ -40,7 +41,7 @@ static void sig_handler_common(int sig, mcontext_t *mc) · 9 unmodified lines | ||
| 40 | 41 | if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM)) |
| 41 | 42 | unblock_signals(); |
| 42 | 43 | |
| 43 | − (*sig_info[sig])(sig, &r); | |
| 44 | + (*sig_info[sig])(sig, si, &r); | |
| 44 | 45 | |
| 45 | 46 | errno = save_errno; |
| 46 | 47 | } |
| @@ -60,7 +61,7 @@ static void sig_handler_common(int sig, mcontext_t *mc) · 13 unmodified lines | ||
| 60 | 61 | static int signals_enabled; |
| 61 | 62 | static unsigned int signals_pending; |
| 62 | 63 | |
| 63 | −void sig_handler(int sig, mcontext_t *mc) | |
| 64 | +void sig_handler(int sig, siginfo_t *si, mcontext_t *mc) | |
| 64 | 65 | { |
| 65 | 66 | int enabled; |
| 66 | 67 | |
| @@ -72,7 +73,7 @@ void sig_handler(int sig, mcontext_t *mc) · 5 unmodified lines | ||
| 72 | 73 | |
| 73 | 74 | block_signals(); |
| 74 | 75 | |
| 75 | − sig_handler_common(sig, mc); | |
| 76 | + sig_handler_common(sig, si, mc); | |
| 76 | 77 | |
| 77 | 78 | set_signals(enabled); |
| 78 | 79 | } |
| @@ -85,10 +86,10 @@ static void real_alarm_handler(mcontext_t *mc) · 6 unmodified lines | ||
| 85 | 86 | get_regs_from_mc(®s, mc); |
| 86 | 87 | regs.is_user = 0; |
| 87 | 88 | unblock_signals(); |
| 88 | − timer_handler(SIGVTALRM, ®s); | |
| 89 | + timer_handler(SIGVTALRM, NULL, ®s); | |
| 89 | 90 | } |
| 90 | 91 | |
| 91 | −void alarm_handler(int sig, mcontext_t *mc) | |
| 92 | +void alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc) | |
| 92 | 93 | { |
| 93 | 94 | int enabled; |
| 94 | 95 | |
| @@ -119,7 +120,7 @@ void set_sigstack(void *sig_stack, int size) · 24 unmodified lines | ||
| 119 | 120 | panic("enabling signal stack failed, errno = %d\n", errno); |
| 120 | 121 | } |
| 121 | 122 | |
| 122 | −static void (*handlers[_NSIG])(int sig, mcontext_t *mc) = { | |
| 123 | +static void (*handlers[_NSIG])(int sig, siginfo_t *si, mcontext_t *mc) = { | |
| 123 | 124 | [SIGSEGV] = sig_handler, |
| 124 | 125 | [SIGBUS] = sig_handler, |
| 125 | 126 | [SIGILL] = sig_handler, |
| @@ -132,7 +133,7 @@ static void (*handlers[_NSIG])(int sig, mcontext_t *mc) = { · 6 unmodified lines | ||
| 132 | 133 | }; |
| 133 | 134 | |
| 134 | 135 | |
| 135 | −static void hard_handler(int sig, siginfo_t *info, void *p) | |
| 136 | +static void hard_handler(int sig, siginfo_t *si, void *p) | |
| 136 | 137 | { |
| 137 | 138 | struct ucontext *uc = p; |
| 138 | 139 | mcontext_t *mc = &uc->uc_mcontext; |
| @@ -161,7 +162,7 @@ static void hard_handler(int sig, siginfo_t *info, void *p) · 22 unmodified lines | ||
| 161 | 162 | while ((sig = ffs(pending)) != 0){ |
| 162 | 163 | sig--; |
| 163 | 164 | pending &= ~(1 << sig); |
| 164 | − (*handlers[sig])(sig, mc); | |
| 165 | + (*handlers[sig])(sig, si, mc); | |
| 165 | 166 | } |
| 166 | 167 | |
| 167 | 168 | /* |
| @@ -273,9 +274,12 @@ void unblock_signals(void) · 105 unmodified lines | ||
| 273 | 274 | * Deal with SIGIO first because the alarm handler might |
| 274 | 275 | * schedule, leaving the pending SIGIO stranded until we come |
| 275 | 276 | * back here. |
| 277 | + * | |
| 278 | + * SIGIO's handler doesn't use siginfo or mcontext, | |
| 279 | + * so they can be NULL. | |
| 276 | 280 | */ |
| 277 | 281 | if (save_pending & SIGIO_MASK) |
| 278 | − sig_handler_common(SIGIO, NULL); | |
| 282 | + sig_handler_common(SIGIO, NULL, NULL); | |
| 279 | 283 | |
| 280 | 284 | if (save_pending & SIGVTALRM_MASK) |
| 281 | 285 | real_alarm_handler(NULL); |
| @@ -346,6 +346,10 @@ void userspace(struct uml_pt_regs *regs) · 345 unmodified lines | ||
| 346 | 346 | int err, status, op, pid = userspace_pid[0]; |
| 347 | 347 | /* To prevent races if using_sysemu changes under us.*/ |
| 348 | 348 | int local_using_sysemu; |
| 349 | + siginfo_t si; | |
| 350 | + | |
| 351 | + /* Handle any immediate reschedules or signals */ | |
| 352 | + interrupt_end(); | |
| 349 | 353 | |
| 350 | 354 | if (getitimer(ITIMER_VIRTUAL, &timer)) |
| 351 | 355 | printk(UM_KERN_ERR "Failed to get itimer, errno = %d\n", errno); |
| @@ -404,13 +408,17 @@ void userspace(struct uml_pt_regs *regs) · 52 unmodified lines | ||
| 404 | 408 | |
| 405 | 409 | if (WIFSTOPPED(status)) { |
| 406 | 410 | int sig = WSTOPSIG(status); |
| 411 | + | |
| 412 | + ptrace(PTRACE_GETSIGINFO, pid, 0, &si); | |
| 413 | + | |
| 407 | 414 | switch (sig) { |
| 408 | 415 | case SIGSEGV: |
| 409 | 416 | if (PTRACE_FULL_FAULTINFO || |
| 410 | 417 | !ptrace_faultinfo) { |
| 411 | 418 | get_skas_faultinfo(pid, |
| 412 | 419 | ®s->faultinfo); |
| 413 | − (*sig_info[SIGSEGV])(SIGSEGV, regs); | |
| 420 | + (*sig_info[SIGSEGV])(SIGSEGV, &si, | |
| 421 | + regs); | |
| 414 | 422 | } |
| 415 | 423 | else handle_segv(pid, regs); |
| 416 | 424 | break; |
| @@ -418,14 +426,14 @@ void userspace(struct uml_pt_regs *regs) · 1 unmodified line | ||
| 418 | 426 | handle_trap(pid, regs, local_using_sysemu); |
| 419 | 427 | break; |
| 420 | 428 | case SIGTRAP: |
| 421 | − relay_signal(SIGTRAP, regs); | |
| 429 | + relay_signal(SIGTRAP, &si, regs); | |
| 422 | 430 | break; |
| 423 | 431 | case SIGVTALRM: |
| 424 | 432 | now = os_nsecs(); |
| 425 | 433 | if (now < nsecs) |
| 426 | 434 | break; |
| 427 | 435 | block_signals(); |
| 428 | − (*sig_info[sig])(sig, regs); | |
| 436 | + (*sig_info[sig])(sig, &si, regs); | |
| 429 | 437 | unblock_signals(); |
| 430 | 438 | nsecs = timer.it_value.tv_sec * |
| 431 | 439 | UM_NSEC_PER_SEC + |
| @@ -439,7 +447,7 @@ void userspace(struct uml_pt_regs *regs) · 7 unmodified lines | ||
| 439 | 447 | case SIGFPE: |
| 440 | 448 | case SIGWINCH: |
| 441 | 449 | block_signals(); |
| 442 | − (*sig_info[sig])(sig, regs); | |
| 450 | + (*sig_info[sig])(sig, &si, regs); | |
| 443 | 451 | unblock_signals(); |
| 444 | 452 | break; |
| 445 | 453 | default: |
| @@ -87,7 +87,7 @@ static int after_sleep_interval(struct timespec *ts) · 86 unmodified lines | ||
| 87 | 87 | |
| 88 | 88 | static void deliver_alarm(void) |
| 89 | 89 | { |
| 90 | − alarm_handler(SIGVTALRM, NULL); | |
| 90 | + alarm_handler(SIGVTALRM, NULL, NULL); | |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | 93 | static unsigned long long sleep_time(unsigned long long nsecs) |
| @@ -30,10 +30,10 @@ · 29 unmodified lines | ||
| 30 | 30 | #define profile_pc(regs) PT_REGS_IP(regs) |
| 31 | 31 | |
| 32 | 32 | #define UPT_RESTART_SYSCALL(r) (UPT_IP(r) -= 2) |
| 33 | −#define UPT_SET_SYSCALL_RETURN(r, res) (UPT_AX(r) = (res)) | |
| 33 | +#define PT_REGS_SET_SYSCALL_RETURN(r, res) (PT_REGS_AX(r) = (res)) | |
| 34 | 34 | |
| 35 | −static inline long regs_return_value(struct uml_pt_regs *regs) | |
| 35 | +static inline long regs_return_value(struct pt_regs *regs) | |
| 36 | 36 | { |
| 37 | − return UPT_AX(regs); | |
| 37 | + return PT_REGS_AX(regs); | |
| 38 | 38 | } |
| 39 | 39 | #endif /* __UM_X86_PTRACE_H */ |