6613318 can't restart init in branded zones
6703962 sn1 brand is broken on x86 post b75
--- a/usr/src/uts/common/brand/sn1/sn1_brand.c Tue Jul 01 12:52:38 2008 -0700
+++ b/usr/src/uts/common/brand/sn1/sn1_brand.c Tue Jul 01 13:21:08 2008 -0700
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -133,8 +133,16 @@
void
sn1_setbrand(proc_t *p)
{
+ ASSERT(p->p_brand == &sn1_brand);
+ ASSERT(p->p_brand_data == NULL);
p->p_brand_data = NULL;
- p->p_brand = &sn1_brand;
+
+ /*
+ * We should only be called from exec(), when we know the process
+ * is single-threaded.
+ */
+ ASSERT(p->p_tlist == p->p_tlist->t_forw);
+ (void) sn1_initlwp(p->p_tlist->t_lwp);
}
/* ARGSUSED */
@@ -163,14 +171,28 @@
proc_t *p = curproc;
*rval = 0;
+ /*
+ * There is one operation that is suppored for non-branded
+ * process. B_EXEC_BRAND. This brand operaion is redundant
+ * since the kernel assumes a native process doing an exec
+ * in a branded zone is going to run a branded processes.
+ * hence we don't support this operation.
+ */
+ if (cmd == B_EXEC_BRAND)
+ return (ENOSYS);
+
+ /* For all other operations this must be a branded process. */
+ if (p->p_brand == &native_brand)
+ return (ENOSYS);
+
+ ASSERT(p->p_brand == &sn1_brand);
+
if (cmd == B_REGISTER) {
- p->p_brand = &sn1_brand;
- p->p_brand_data = (void *) arg1;
+ ASSERT(p->p_brand_data == NULL);
+ p->p_brand_data = (void *)arg1;
return (0);
}
- ASSERT(p->p_brand == &sn1_brand);
-
return (EINVAL);
}
@@ -182,20 +204,41 @@
void
sn1_copy_procdata(proc_t *child, proc_t *parent)
{
- child->p_brand_data = parent->p_brand_data;
+ ASSERT(parent->p_brand == &sn1_brand);
+ ASSERT(child->p_brand == &sn1_brand);
+
+ child->p_brand_data = NULL;
}
/*ARGSUSED*/
void
sn1_proc_exit(struct proc *p, klwp_t *l)
{
+ ASSERT(p->p_brand == &sn1_brand);
+
+ /*
+ * We should only be called from proc_exit(), when we know that
+ * process is single-threaded.
+ */
+ ASSERT(p->p_tlist == p->p_tlist->t_forw);
+
p->p_brand_data = NULL;
- p->p_brand = &native_brand;
+ l->lwp_brand = NULL;
}
void
sn1_exec()
{
+ ASSERT(curproc->p_brand == &sn1_brand);
+ ASSERT(ttolwp(curthread)->lwp_brand != NULL);
+
+ /*
+ * We should only be called from exec(), when we know the process
+ * is single-threaded.
+ */
+ ASSERT(curproc->p_tlist == curproc->p_tlist->t_forw);
+
+ /* upon exec, reset our user-land handler callback entry point */
curproc->p_brand_data = NULL;
}
@@ -203,11 +246,55 @@
int
sn1_initlwp(klwp_t *l)
{
+ ASSERT(l->lwp_procp->p_brand == &sn1_brand);
+ ASSERT(l->lwp_brand == NULL);
+ l->lwp_brand = (void *)-1;
return (0);
}
/*ARGSUSED*/
void
+sn1_forklwp(klwp_t *p, klwp_t *c)
+{
+ ASSERT(p->lwp_procp->p_brand == &sn1_brand);
+ ASSERT(c->lwp_procp->p_brand == &sn1_brand);
+
+ /* Both LWPs have already had been initialized via sn1_initlwp() */
+ ASSERT(p->lwp_brand != NULL);
+ ASSERT(c->lwp_brand != NULL);
+}
+
+/*ARGSUSED*/
+void
+sn1_freelwp(klwp_t *l)
+{
+ /* This lwp died during birth */
+ ASSERT(l->lwp_procp->p_brand == &sn1_brand);
+ ASSERT(l->lwp_brand != NULL);
+ l->lwp_brand = NULL;
+}
+
+/*ARGSUSED*/
+void
+sn1_lwpexit(klwp_t *l)
+{
+ proc_t *p = l->lwp_procp;
+
+ ASSERT(l->lwp_procp->p_brand == &sn1_brand);
+ ASSERT(l->lwp_brand != NULL);
+
+ /*
+ * We should never be called for the last thread in a process.
+ * (That case is handled by sn1_proc_exit().) There for this lwp
+ * must be exiting from a multi-threaded process.
+ */
+ ASSERT(p->p_tlist != p->p_tlist->t_forw);
+
+ l->lwp_brand = NULL;
+}
+
+/*ARGSUSED*/
+void
sn1_init_brand_data(zone_t *zone)
{
}
@@ -218,24 +305,6 @@
{
}
-/*ARGSUSED*/
-void
-sn1_forklwp(klwp_t *p, klwp_t *c)
-{
-}
-
-/*ARGSUSED*/
-void
-sn1_freelwp(klwp_t *l)
-{
-}
-
-/*ARGSUSED*/
-void
-sn1_lwpexit(klwp_t *l)
-{
-}
-
int
sn1_elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
int level, long *execsz, int setid, caddr_t exec_file, cred_t *cred,
--- a/usr/src/uts/common/os/brand.c Tue Jul 01 12:52:38 2008 -0700
+++ b/usr/src/uts/common/os/brand.c Tue Jul 01 13:21:08 2008 -0700
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -333,10 +333,25 @@
ASSERT(p->p_tlist == p->p_tlist->t_forw);
p->p_brand = bp;
- if (PROC_IS_BRANDED(p)) {
- BROP(p)->b_setbrand(p);
- lwp_attach_brand_hdlrs(p->p_tlist->t_lwp);
- }
+ ASSERT(PROC_IS_BRANDED(p));
+ BROP(p)->b_setbrand(p);
+}
+
+void
+brand_clearbrand(proc_t *p)
+{
+ brand_t *bp = p->p_zone->zone_brand;
+ ASSERT(bp != NULL);
+
+ /*
+ * We should only be called from exec_common() or proc_exit(),
+ * when we know the process is single-threaded.
+ */
+ ASSERT(p->p_tlist == p->p_tlist->t_forw);
+
+ ASSERT(PROC_IS_BRANDED(p));
+ BROP(p)->b_proc_exit(p, p->p_tlist->t_lwp);
+ p->p_brand = &native_brand;
}
#if defined(__sparcv9)
--- a/usr/src/uts/common/os/exec.c Tue Jul 01 12:52:38 2008 -0700
+++ b/usr/src/uts/common/os/exec.c Tue Jul 01 13:21:08 2008 -0700
@@ -138,7 +138,7 @@
lwpdir_t **old_tidhash;
uint_t old_tidhash_sz;
lwpent_t *lep;
- int brandme = 0;
+ boolean_t brandme = B_FALSE;
/*
* exec() is not supported for the /proc agent lwp.
@@ -162,7 +162,7 @@
/* Only unbranded processes can be branded */
if (PROC_IS_BRANDED(p))
return (ENOTSUP);
- brandme = 1;
+ brandme = B_TRUE;
}
} else {
/*
@@ -172,7 +172,7 @@
* process as it exec()s the new binary.
*/
if (ZONE_IS_BRANDED(p->p_zone) && !PROC_IS_BRANDED(p))
- brandme = 1;
+ brandme = B_TRUE;
}
/*
@@ -276,13 +276,13 @@
ua.envp = envp;
/* If necessary, brand this process before we start the exec. */
- if (brandme != 0)
+ if (brandme)
brand_setbrand(p);
if ((error = gexec(&vp, &ua, &args, NULL, 0, &execsz,
exec_file, p->p_cred, brand_action)) != 0) {
- if (brandme != 0)
- BROP(p)->b_proc_exit(p, lwp);
+ if (brandme)
+ brand_clearbrand(p);
VN_RELE(vp);
if (dir != NULL)
VN_RELE(dir);
@@ -396,10 +396,9 @@
close_exec(P_FINFO(p));
TRACE_2(TR_FAC_PROC, TR_PROC_EXEC, "proc_exec:p %p up %p", p, up);
- /* Unbrand ourself if requested. */
- if (brand_action == EBA_NATIVE)
- BROP(p)->b_proc_exit(p, lwp);
- ASSERT((brand_action != EBA_NATIVE) || !PROC_IS_BRANDED(p));
+ /* Unbrand ourself if necessary. */
+ if (PROC_IS_BRANDED(p) && (brand_action == EBA_NATIVE))
+ brand_clearbrand(p);
setregs(&args);
--- a/usr/src/uts/common/os/exit.c Tue Jul 01 12:52:38 2008 -0700
+++ b/usr/src/uts/common/os/exit.c Tue Jul 01 13:21:08 2008 -0700
@@ -375,8 +375,10 @@
* is always the last lwp, will also perform lwp_exit and free brand
* data
*/
- if (PROC_IS_BRANDED(p))
- BROP(p)->b_proc_exit(p, lwp);
+ if (PROC_IS_BRANDED(p)) {
+ lwp_detach_brand_hdlrs(lwp);
+ brand_clearbrand(p);
+ }
/*
* Don't let init exit unless zone_start_init() failed its exec, or
--- a/usr/src/uts/common/sys/brand.h Tue Jul 01 12:52:38 2008 -0700
+++ b/usr/src/uts/common/sys/brand.h Tue Jul 01 13:21:08 2008 -0700
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -127,6 +127,7 @@
extern void brand_unregister_zone(brand_t *);
extern int brand_zone_count(brand_t *);
extern void brand_setbrand(proc_t *);
+extern void brand_clearbrand(proc_t *);
#endif /* _KERNEL */
#ifdef __cplusplus
--- a/usr/src/uts/common/sys/proc.h Tue Jul 01 12:52:38 2008 -0700
+++ b/usr/src/uts/common/sys/proc.h Tue Jul 01 13:21:08 2008 -0700
@@ -748,6 +748,7 @@
extern int lwp_setprivate(klwp_t *, int, uintptr_t);
extern void lwp_stat_update(lwp_stat_id_t, long);
extern void lwp_attach_brand_hdlrs(klwp_t *);
+extern void lwp_detach_brand_hdlrs(klwp_t *);
/*
* Signal queue function prototypes. Must be here due to header ordering
--- a/usr/src/uts/intel/brand/sn1/sn1_brand_asm.s Tue Jul 01 12:52:38 2008 -0700
+++ b/usr/src/uts/intel/brand/sn1/sn1_brand_asm.s Tue Jul 01 13:21:08 2008 -0700
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -34,6 +34,7 @@
#include <sys/asm_linkage.h>
#include <sys/privregs.h>
#include <sys/segments.h>
+#include "assym.h"
#endif /* lint */
@@ -63,6 +64,81 @@
#else /* lint */
+#if defined(__amd64)
+/*
+ * When our syscall interposition callback entry point gets invoked the
+ * stack looks like this:
+ * --------------------------------------
+ * 24 | saved stack pointer |
+ * | 16 | lwp pointer |
+ * v 8 | user return address (*) |
+ * 0 | BRAND_CALLBACK()'s return addr |
+ * --------------------------------------
+ * (*) This is actually just the bottom value from the user's
+ * stack. syscall puts this in %rcx instead of the stack,
+ * so it's just garbage for that entry point.
+ */
+
+#define V_COUNT 4
+#define V_END (CLONGSIZE * 4)
+#define V_SSP (CLONGSIZE * 3)
+#define V_LWP (CLONGSIZE * 2)
+#define V_URET_ADDR (CLONGSIZE * 1)
+#define V_CB_ADDR (CLONGSIZE * 0)
+
+#define SP_REG %rsp
+
+#else /* !__amd64 */
+/*
+ * When our syscall interposition callback entry point gets invoked the
+ * stack looks like this:
+ * --------------------------------------
+ * | 24 | 'scatch space' |
+ * | 20 | user's %ebx |
+ * | 16 | user's %gs selector |
+ * | 12 | kernel's %gs selector |
+ * | 8 | lwp pointer |
+ * v 4 | user return address |
+ * 0 | callback wrapper return addr |
+ * --------------------------------------
+ */
+
+#define V_COUNT 7
+#define V_END (CLONGSIZE * 7)
+#define V_LWP (CLONGSIZE * 2)
+#define V_URET_ADDR (CLONGSIZE * 1)
+#define V_CB_ADDR (CLONGSIZE * 0)
+
+#define SP_REG %esp
+
+#endif /* !__amd64 */
+
+/*
+ * The following macros allow us to access to variables/parameters passed
+ * in on the stack. They take the following variables:
+ * sp - a register with the current stack pointer value
+ * pcnt - the number of words currently pushed onto the stack
+ * var - the variable to lookup
+ * reg - a register to read the variable into, or
+ * a register to write to the variable
+ */
+#define V_OFFSET(pcnt, var) \
+ (var + (pcnt * CLONGSIZE))
+
+#define GET_V(sp, pcnt, var, reg) \
+ mov V_OFFSET(pcnt, var)(sp), reg
+
+#define SET_V(sp, pcnt, var, reg) \
+ mov reg, V_OFFSET(pcnt, var)(sp)
+
+#define GET_PROCP(sp, pcnt, reg) \
+ GET_V(sp, pcnt, V_LWP, reg) /* get lwp pointer */ ;\
+ mov LWP_PROCP(reg), reg /* get proc pointer */
+
+#define GET_P_BRAND_DATA(sp, pcnt, reg) \
+ GET_PROCP(sp, pcnt, reg) ;\
+ mov P_BRAND_DATA(reg), reg /* get p_brand_data */
+
/*
* Each of the following macros returns to the standard syscall codepath if
* it detects that this process is not able, or intended, to emulate this
@@ -71,27 +147,22 @@
*/
/*
- * See if this process has a user-space handler registered for it. For the
+ * See if this process has a user-space hdlr registered for it. For the
* sn1 brand, the per-process brand data holds the address of the handler.
- * As shown in the stack diagrams below, the callback code leaves that data
+ * As shown in the stack diagrams above, the callback code leaves that data
* at these offsets.
*/
-#if defined(__amd64)
-#define CHECK_FOR_HANDLER \
- cmpq $0, 24(%rsp) ;\
- je 9f
-#else
-#define CHECK_FOR_HANDLER \
- cmpl $0, 12(%esp) ;\
- je 9f
-#endif /* __amd64 */
+#define CHECK_FOR_HANDLER(scr) \
+ GET_PROCP(SP_REG, 1, scr) /* get proc pointer */ ;\
+ cmp $0, P_BRAND_DATA(scr) /* check p_brand_data */ ;\
+ je 9f
-/*
+/*
* If the system call number is >= 1024, then it is coming from the
* emulation support library. As such we should handle it natively instead
* of sending it back to the emulation library.
*/
-#define CHECK_FOR_NATIVE(reg) \
+#define CHECK_FOR_NATIVE(reg) \
cmp $1024, reg ;\
jl 1f ;\
sub $1024, reg ;\
@@ -102,17 +173,17 @@
* Check to see if we want to interpose on this system call. If not, we
* jump back into the normal syscall path and pretend nothing happened.
*/
-#define CHECK_FOR_INTERPOSITION(sysr, scr, scr_low) \
+#define CHECK_FOR_INTERPOSITION(sysr, scr, scr_low) \
lea sn1_emulation_table, scr ;\
mov (scr), scr ;\
add sysr, scr ;\
movb (scr), scr_low ;\
cmpb $0, scr_low ;\
- je 9f ;\
+ je 9f
-#define CALLBACK_PROLOGUE(call, scr, scr_low) ;\
+#define CALLBACK_PROLOGUE(call, scr, scr_low) \
push scr /* Save scratch register */ ;\
- CHECK_FOR_HANDLER ;\
+ CHECK_FOR_HANDLER(scr) ;\
CHECK_FOR_NATIVE(call) ;\
CHECK_FOR_INTERPOSITION(call, scr, scr_low)
@@ -121,120 +192,104 @@
*/
#if defined(__amd64)
- /*
- * When we get into any of these callback routines, the stack
- * looks like this:
- * --------------------------------------
- * 32 | saved stack pointer |
- * | 24 | lwp brand data |
- * | 16 | proc brand data |
- * v 8 | user return address (*) |
- * 0 | BRAND_CALLBACK()'s return addr |
- * --------------------------------------
- * (*) This is actually just the bottom value from the user's
- * stack. syscall puts this in %rcx instead of the stack,
- * so it's just garbage for that entry point.
- */
- /*
- * syscall handler for 32-bit user processes:
- *
- * %ecx contains the address of the instruction after the syscall
- */
- ENTRY(sn1_brand_syscall32_callback)
+/*
+ * syscall handler for 32-bit user processes:
+ * %rax - syscall number
+ * %ecx - the address of the instruction after the syscall
+ */
+ENTRY(sn1_brand_syscall32_callback)
CALLBACK_PROLOGUE(%rax, %r15, %r15b)
-
movq %rsp, %r15 /* save our stack pointer */
/*
- * Adjust the user's stack so that the 'ret' from our userspace
- * handler takes us to the post-syscall instruction instead of to
+ * Adjust the user's stack so that the 'ret' from our user-space
+ * hdlr takes us to the post-syscall instruction instead of to
* the routine that called the system call.
*/
- movq 40(%rsp), %rsp /* restore user's stack pointer */
+ GET_V(%r15, 1, V_SSP, %rsp) /* restore user's stack pointer */
subq $4, %rsp /* save room for the post-syscall addr */
movl %ecx, (%rsp) /* Save post-syscall addr on stack */
/*
- * To 'return' to our user-space handler, we just need to copy
- * its address into %ecx.
+ * To 'return' to our user-space hdlr, we just need to copy
+ * its address into %ecx. user-space hdlr == p_brand_data for sn1
*/
- movq 24(%r15), %rcx /* user-space handler == proc_data for sn1 */
+ GET_P_BRAND_DATA(%r15, 1, %rcx);
movq (%r15), %r15 /* Restore scratch register */
jmp nopop_sys_syscall32_sysretl
9:
popq %r15
retq
- SET_SIZE(sn1_brand_syscall32_callback)
+SET_SIZE(sn1_brand_syscall32_callback)
- /*
- * syscall handler for 64-bit user processes:
- * %rax - syscall number
- * %rcx - user space %rip
- */
- ENTRY(sn1_brand_syscall_callback)
+/*
+ * syscall handler for 64-bit user processes:
+ * %rax - syscall number
+ * %rcx - user space %rip
+ */
+ENTRY(sn1_brand_syscall_callback)
CALLBACK_PROLOGUE(%rax, %r15, %r15b)
-
movq %rsp, %r15 /* save our stack pointer */
- movq 40(%rsp), %rsp /* restore user's stack pointer */
+ GET_V(%r15, 1, V_SSP, %rsp) /* restore user's stack pointer */
subq $8, %rsp /* save room for the post-syscall addr */
movq %rcx, (%rsp) /* Save post-syscall addr on stack */
/*
- * To 'return' to our user-space handler, we just need to copy
- * its address into %ecx.
+ * To 'return' to our user-space hdlr, we just need to copy
+ * its address into %ecx. user-space hdlr == p_brand_data for sn1
*/
- movq 24(%r15), %rcx /* user-space handler == proc_data for sn1 */
+ GET_P_BRAND_DATA(%r15, 1, %rcx);
movq (%r15), %r15 /* Restore scratch register */
jmp nopop_sys_syscall_sysretq
9:
popq %r15
retq
-
- SET_SIZE(sn1_brand_syscall_callback)
+
+SET_SIZE(sn1_brand_syscall_callback)
- /*
- * %rax - syscall number
- * %rcx - user space %esp
- * %rdx - user space return address
- *
- * XXX: not tested yet. Need a Nocona machine first.
- */
- ENTRY(sn1_brand_sysenter_callback)
+/*
+ * %rax - syscall number
+ * %rcx - user space %esp
+ * %rdx - user space return address
+ *
+ * XXX: not tested yet. Need a Nocona machine first.
+ */
+ENTRY(sn1_brand_sysenter_callback)
CALLBACK_PROLOGUE(%rax, %r15, %r15b)
- subq $4, %rcx /* Save room for user ret addr */
- movq %rdx, (%rcx) /* Save current return addr */
- movq 24(%rsp), %rdx /* user-space handler == proc_data for sn1 */
- popq %r15
+ subq $4, %rcx /* Save room for user ret addr */
+ movq %rdx, (%rcx) /* Save current return addr */
+ GET_P_BRAND_DATA(%rsp, 1, %rdx) /* get p_brand_data */
+ popq %r15 /* Restore scratch register */
sysexit
9:
popq %r15
ret
- SET_SIZE(sn1_brand_sysenter_callback)
+SET_SIZE(sn1_brand_sysenter_callback)
- /*
- * The saved stack pointer points at the state saved when we took
- * the interrupt:
- * --------------------------------------
- * | 32 | user's %ss |
- * | 24 | user's %esp |
- * | 16 | EFLAGS register |
- * v 8 | user's %cs |
- * 0 | user's %eip |
- * --------------------------------------
- */
- ENTRY(sn1_brand_int91_callback)
+/*
+ * The saved stack pointer points at the state saved when we took
+ * the interrupt:
+ * --------------------------------------
+ * | 32 | user's %ss |
+ * | 24 | user's %esp |
+ * | 16 | EFLAGS register |
+ * v 8 | user's %cs |
+ * 0 | user's %eip |
+ * --------------------------------------
+ */
+ENTRY(sn1_brand_int91_callback)
CALLBACK_PROLOGUE(%rax, %r15, %r15b)
+ pushq %rax /* Save scratch register */
- movq 24(%rsp), %r15 /* user-space handler == proc_data for sn1 */
- pushq %rax /* Save scratch register */
- movq 48(%rsp), %rax /* Get saved %esp */
+ GET_P_BRAND_DATA(%rsp, 2, %r15) /* get p_brand_data */
+ GET_V(%rsp, 2, V_SSP, %rax) /* Get saved %esp */
movq %r15, (%rax) /* replace iret target address with hdlr */
/*
@@ -245,96 +300,88 @@
movq 24(%rax), %r15 /* Get user's %esp */
subq $4, %r15 /* Make room for new ret addr */
movq %r15, 24(%rax) /* Replace current with updated %esp */
- movl 24(%rsp), %eax /* Get post-syscall address */
+
+ GET_V(%rsp, 2, V_URET_ADDR, %rax)
movl %eax, (%r15) /* Put it on the user's stack */
- popq %rax /* Restore scratch register */
- popq %r15 /* Restore scratch register */
- movq 32(%rsp), %rsp /* Remove all callback stuff from stack */
+ popq %rax /* Restore scratch register */
+ popq %r15 /* Restore scratch register */
+ movq V_SSP(%rsp), %rsp /* Remove callback stuff from stack */
jmp nopop_sys_rtt_syscall32
9:
popq %r15
retq
- SET_SIZE(sn1_brand_int91_callback)
+SET_SIZE(sn1_brand_int91_callback)
-#else /* __amd64 */
+#else /* !__amd64 */
- /*
- * When we get into any of these callback routines, the stack
- * looks like this:
- * --------------------------------------
- * | 28 | 'scatch space' |
- * | 24 | user's %ebx |
- * | 20 | user's %gs selector |
- * | 16 | kernel's %gs selector |
- * | 12 | lwp brand data |
- * | 8 | proc brand data |
- * v 4 | user return address |
- * 0 | callback wrapper return addr |
- * --------------------------------------
- */
+/*
+ * lcall handler for 32-bit OS
+ * %eax - syscall number
+ *
+ * Above the stack contents common to all callbacks is the
+ * int/lcall-specific state:
+ * --------------------------------------
+ * | 44 | user's %ss |
+ * | 40 | user's %esp |
+ * | 36 | EFLAGS register |
+ * v 32 | user's %cs |
+ * 28 | user's %eip |
+ * --------------------------------------
+ */
+#define V_U_SS (V_END + (CLONGSIZE * 4))
+#define V_U_ESP (V_END + (CLONGSIZE * 3))
+#define V_EFLAGS (V_END + (CLONGSIZE * 2))
+#define V_U_CS (V_END + (CLONGSIZE * 1))
+#define V_U_EIP (V_END + (CLONGSIZE * 0))
- /*
- * lcall handler for 32-bit OS
- * %eax - syscall number
- *
- * Above the stack contents common to all callbacks is the
- * int/lcall-specific state:
- * --------------------------------------
- * | 48 | user's %ss |
- * | 44 | user's %esp |
- * | 40 | EFLAGS register |
- * v 36 | user's %cs |
- * 32 | user's %eip |
- * --------------------------------------
- */
- ENTRY(sn1_brand_syscall_callback)
+ENTRY(sn1_brand_syscall_callback)
CALLBACK_PROLOGUE(%eax, %ebx, %bl)
+ pushl %eax /* Save scratch register */
- movl 12(%esp), %ebx /* user-space handler == proc_data for sn1 */
- movl %ebx, 36(%esp) /* replace iret target address with hdlr */
+ /* replace iret target address with user-space hdlr */
+ GET_P_BRAND_DATA(%esp, 2, %ebx)
+ SET_V(%esp, 2, V_U_EIP, %ebx)
/*
* Adjust the caller's stack so we return to the instruction after
* the syscall on the next 'ret' in userspace - not to the parent
* routine.
*/
- pushl %eax /* Save scratch register */
- movl 52(%esp), %eax /* Get current %esp */
- subl $4, %eax /* Make room for new ret addr */
- movl %eax, 52(%esp) /* Replace current with updated %esp */
- movl 12(%esp), %ebx /* Get post-syscall address */
- movl %ebx, (%eax) /* Put it on the user's stack */
+ GET_V(%esp, 2, V_URET_ADDR, %ebx) /* Get new post-syscall ret addr */
+ GET_V(%esp, 2, V_U_ESP, %eax) /* Get user %esp */
+ subl $4, %eax /* Make room for new ret addr */
+ SET_V(%esp, 2, V_U_ESP, %eax) /* Updated user %esp */
+ movl %ebx, (%eax) /* Put new ret addr on user stack */
+
popl %eax /* Restore scratch register */
-
popl %ebx /* Restore scratch register */
- addl $32, %esp /* Remove all callback stuff from stack */
+ addl $V_END, %esp /* Remove all callback stuff from stack */
jmp nopop_sys_rtt_syscall
9:
popl %ebx
ret
- SET_SIZE(sn1_brand_syscall_callback)
+SET_SIZE(sn1_brand_syscall_callback)
- /*
- * %eax - syscall number
- * %ecx - user space %esp
- * %edx - user space return address
- */
- ENTRY(sn1_brand_sysenter_callback)
+/*
+ * %eax - syscall number
+ * %ecx - user space %esp
+ * %edx - user space return address
+ */
+ENTRY(sn1_brand_sysenter_callback)
CALLBACK_PROLOGUE(%eax, %ebx, %bl)
- subl $4, %ecx /* Save room for user ret addr */
- movl %edx, (%ecx) /* Save current return addr */
- movl 12(%esp), %edx /* Return to user-space handler */
- popl %ebx /* Restore scratch register */
+ subl $4, %ecx /* Save room for user ret addr */
+ movl %edx, (%ecx) /* Save current return addr */
+ GET_P_BRAND_DATA(%esp, 1, %edx) /* get p_brand_data */
+ popl %ebx /* Restore scratch register */
sysexit
9:
popl %ebx
ret
- SET_SIZE(sn1_brand_sysenter_callback)
+SET_SIZE(sn1_brand_sysenter_callback)
-#endif /* __amd64 */
+#endif /* !__amd64 */
#endif /* lint */
-
--- a/usr/src/uts/intel/ia32/os/sundep.c Tue Jul 01 12:52:38 2008 -0700
+++ b/usr/src/uts/intel/ia32/os/sundep.c Tue Jul 01 13:21:08 2008 -0700
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -738,10 +738,10 @@
kthread_t *t = lwptot(lwp);
ASSERT(PROC_IS_BRANDED(lwptoproc(lwp)));
+
ASSERT(removectx(t, NULL, brand_interpositioning_disable,
brand_interpositioning_enable, NULL, NULL,
brand_interpositioning_disable, NULL) == 0);
-
installctx(t, NULL, brand_interpositioning_disable,
brand_interpositioning_enable, NULL, NULL,
brand_interpositioning_disable, NULL);
@@ -754,6 +754,32 @@
}
/*
+ * If this is a process in a branded zone, then we want it to disable the
+ * brand syscall entry points. This routine must be called when the last
+ * lwp in a process is exiting in proc_exit().
+ */
+void
+lwp_detach_brand_hdlrs(klwp_t *lwp)
+{
+ kthread_t *t = lwptot(lwp);
+
+ ASSERT(PROC_IS_BRANDED(lwptoproc(lwp)));
+ if (t == curthread)
+ kpreempt_disable();
+
+ /* Remove the original context handlers */
+ VERIFY(removectx(t, NULL, brand_interpositioning_disable,
+ brand_interpositioning_enable, NULL, NULL,
+ brand_interpositioning_disable, NULL) != 0);
+
+ if (t == curthread) {
+ /* Cleanup our MSR and IDT entries. */
+ brand_interpositioning_disable();
+ kpreempt_enable();
+ }
+}
+
+/*
* Add any lwp-associated context handlers to the lwp at the beginning
* of the lwp's useful life.
*
--- a/usr/src/uts/intel/sn1_brand/Makefile Tue Jul 01 12:52:38 2008 -0700
+++ b/usr/src/uts/intel/sn1_brand/Makefile Tue Jul 01 13:21:08 2008 -0700
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -53,7 +53,19 @@
LINT_TARGET = $(MODULE).lint
INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
-INC_PATH += -I$(UTSBASE)/common/brand/sn1
+INC_PATH += -I$(UTSBASE)/common/brand/sn1
+AS_INC_PATH += -I$(UTSBASE)/i86pc/genassym/$(OBJS_DIR)
+
+#
+# Ugh, this is a gross hack. Sn1_brand_asm.s uses lots of defines
+# to simplify variable access. All these defines work fine for amd64
+# compiles because when compiling for amd64 we use the GNU assembler,
+# gas. For 32-bit code we use the Sun assembler, as. Unfortunatly
+# as does not handle certian constructs that gas does. So rather than
+# make our code less readable, we'll just use gas to compile our 32-bit
+# code as well.
+#
+i386_AS = $(amd64_AS)
#
# Default build targets.
--- a/usr/src/uts/sun4/os/machdep.c Tue Jul 01 12:52:38 2008 -0700
+++ b/usr/src/uts/sun4/os/machdep.c Tue Jul 01 13:21:08 2008 -0700
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -263,13 +263,18 @@
}
/*
- * This function is currently unused on sparc.
+ * These function are currently unused on sparc.
*/
/*ARGSUSED*/
void
lwp_attach_brand_hdlrs(klwp_t *lwp)
{}
+/*ARGSUSED*/
+void
+lwp_detach_brand_hdlrs(klwp_t *lwp)
+{}
+
/*
* fill in the extra register state area specified with the
* specified lwp's platform-dependent non-floating-point extra