char c;
if (sdbg_state == SDBG_STATE_WAIT_BRK) {
- (param)->eflags &= ~(1 << 8);
+ (param)->execp->eflags &= ~(1 << 8);
sdbg_state = SDBG_STATE_INSESSION;
- sdbg_printf("[%p:%p] Break point reached.\n", param->cs, param->eip);
+ sdbg_printf("[%p:%p] Break point reached.\n",
+ param->execp->cs,
+ param->execp->eip);
}
while (1) {
switch (c) {
case SDBG_CLNT_HI:
if (sdbg_state == SDBG_STATE_START) {
- sdbg_printf(
- "[%p:%p] Session started.\n", param->cs, param->eip);
+ sdbg_printf("[%p:%p] Session started.\n",
+ param->execp->cs,
+ param->execp->eip);
sdbg_state = SDBG_STATE_INSESSION;
} else {
- sdbg_printf(
- "[%p:%p] Session resumed.\n", param->cs, param->eip);
+ sdbg_printf("[%p:%p] Session resumed.\n",
+ param->execp->cs,
+ param->execp->eip);
}
break;
case SDBG_CLNT_RREG:
serial_tx_buffer(SERIAL_COM1, (char*)param, sizeof(isr_param));
break;
case SDBG_CLNT_STEP:
- ((isr_param*)param)->eflags |= (1 << 8); // set TF flags
+ ((isr_param*)param)->execp->eflags |= (1 << 8); // set TF flags
sdbg_state = SDBG_STATE_WAIT_BRK;
return;
case SDBG_CLNT_BRKP:
gdbstub_loop(isr_param* param)
{
/* Translate vector to signal */
- switch (param->vector) {
+ switch (param->execp->vector) {
case 1:
gdb_state.signum = 5;
break;
gdb_state.registers[GDB_CPU_I386_REG_ECX] = param->registers.ecx;
gdb_state.registers[GDB_CPU_I386_REG_EDX] = param->registers.edx;
gdb_state.registers[GDB_CPU_I386_REG_EBX] = param->registers.ebx;
- gdb_state.registers[GDB_CPU_I386_REG_ESP] = param->registers.esp;
+ gdb_state.registers[GDB_CPU_I386_REG_ESP] = param->esp;
gdb_state.registers[GDB_CPU_I386_REG_EBP] = param->registers.ebp;
gdb_state.registers[GDB_CPU_I386_REG_ESI] = param->registers.esi;
gdb_state.registers[GDB_CPU_I386_REG_EDI] = param->registers.edi;
- gdb_state.registers[GDB_CPU_I386_REG_PC] = param->eip;
- gdb_state.registers[GDB_CPU_I386_REG_CS] = param->cs;
- gdb_state.registers[GDB_CPU_I386_REG_PS] = param->eflags;
- gdb_state.registers[GDB_CPU_I386_REG_SS] = param->ss;
+ gdb_state.registers[GDB_CPU_I386_REG_PC] = param->execp->eip;
+ gdb_state.registers[GDB_CPU_I386_REG_CS] = param->execp->cs;
+ gdb_state.registers[GDB_CPU_I386_REG_PS] = param->execp->eflags;
+ gdb_state.registers[GDB_CPU_I386_REG_SS] = param->execp->ss;
gdb_state.registers[GDB_CPU_I386_REG_DS] = param->registers.ds;
gdb_state.registers[GDB_CPU_I386_REG_ES] = param->registers.es;
gdb_state.registers[GDB_CPU_I386_REG_FS] = param->registers.fs;
param->registers.ecx = gdb_state.registers[GDB_CPU_I386_REG_ECX];
param->registers.edx = gdb_state.registers[GDB_CPU_I386_REG_EDX];
param->registers.ebx = gdb_state.registers[GDB_CPU_I386_REG_EBX];
- param->registers.esp = gdb_state.registers[GDB_CPU_I386_REG_ESP];
+ param->esp = gdb_state.registers[GDB_CPU_I386_REG_ESP];
param->registers.ebp = gdb_state.registers[GDB_CPU_I386_REG_EBP];
param->registers.esi = gdb_state.registers[GDB_CPU_I386_REG_ESI];
param->registers.edi = gdb_state.registers[GDB_CPU_I386_REG_EDI];
- param->eip = gdb_state.registers[GDB_CPU_I386_REG_PC];
- param->cs = gdb_state.registers[GDB_CPU_I386_REG_CS];
- param->eflags = gdb_state.registers[GDB_CPU_I386_REG_PS];
- param->ss = gdb_state.registers[GDB_CPU_I386_REG_SS];
+ param->execp->eip = gdb_state.registers[GDB_CPU_I386_REG_PC];
+ param->execp->cs = gdb_state.registers[GDB_CPU_I386_REG_CS];
+ param->execp->eflags = gdb_state.registers[GDB_CPU_I386_REG_PS];
+ param->execp->ss = gdb_state.registers[GDB_CPU_I386_REG_SS];
param->registers.ds = gdb_state.registers[GDB_CPU_I386_REG_DS];
param->registers.es = gdb_state.registers[GDB_CPU_I386_REG_ES];
param->registers.fs = gdb_state.registers[GDB_CPU_I386_REG_FS];
// synchronized way. And we don't want these irq queue up at our APIC and
// confuse the CPU after ACK with APIC.
serial_disable_irq(SERIAL_COM1);
- if (param->vector == 1 || param->vector == 3) {
+ struct exec_param* execp = param->execp;
+ if (execp->vector == 1 || execp->vector == 3) {
goto cont;
}
void
sdbg_imm(const isr_param* param)
{
+ struct exec_param* execp = param->execp;
kprintf(KDEBUG "Quick debug mode\n");
kprintf(KDEBUG "cs=%p eip=%p eax=%p ebx=%p\n",
- param->cs,
- param->eip,
+ execp->cs,
+ execp->eip,
param->registers.eax,
param->registers.ebx);
kprintf(KDEBUG "ecx=%p edx=%p edi=%p esi=%p\n",
param->registers.edi,
param->registers.esi);
kprintf(KDEBUG "u.esp=%p k.esp=%p ebp=%p ps=%p\n",
- param->registers.esp,
param->esp,
+ execp->esp,
param->registers.ebp,
- param->eflags);
+ execp->eflags);
kprintf(KDEBUG "ss=%p ds=%p es=%p fs=%p gs=%p\n",
- param->ss,
+ execp->ss,
param->registers.ds,
param->registers.es,
param->registers.fs,
struct ahci_driver *pos, *n;
llist_for_each(pos, n, &ahcis, ahci_drvs)
{
- if (pos->id == param->vector) {
+ if (pos->id == param->execp->vector) {
hba = &pos->hba;
goto proceed;
}
#ifndef __ASM__
#include <hal/cpu.h>
+
+struct exec_param
+{
+ unsigned int vector;
+ unsigned int err_code;
+ unsigned int eip;
+ unsigned int cs;
+ unsigned int eflags;
+ unsigned int esp;
+ unsigned int ss;
+} __attribute__((packed));
+
typedef struct
{
struct
reg32 es;
reg32 fs;
reg32 gs;
- reg32 esp;
+ // reg32 esp;
} __attribute__((packed)) registers;
- unsigned int vector;
- unsigned int err_code;
- unsigned int eip;
- unsigned int cs;
- unsigned int eflags;
- unsigned int esp;
- unsigned int ss;
+ union
+ {
+ reg32 esp;
+ struct exec_param* execp;
+ };
} __attribute__((packed)) isr_param;
void
pid_t pid; // offset = 0
struct proc_info* parent; // offset = 4
isr_param intr_ctx; // offset = 8
- uintptr_t ustack_top; // offset = 84
- void* page_table; // offset = 88
- void* fxstate; // offset = 92
+ uintptr_t ustack_top; // offset = 84 -> 56
+ void* page_table; // offset = 88 -> 60
+ void* fxstate; // offset = 92 -> 64
/* ---- critical section end ---- */
movl (__current), %eax
# 保存x87FPU的状态
- movl 92(%eax), %ebx
+ movl 64(%eax), %ebx
fxsave (%ebx)
movl 68(%esp), %ebx # 取出esp
- movl %ebx, 84(%eax) # 存入__current->ustack_top
+ movl %ebx, 56(%eax) # 存入__current->ustack_top
1:
movl %esp, %eax
#ifdef __ASM_INTR_DIAGNOSIS
movl %eax, (debug_resv + 8)
- movl 56(%esp), %eax
- movl %eax, (debug_resv + 4)
+ movl 44(%esp), %eax
+ movl 8(%eax), %eax
+ movl %eax, (debug_resv + 4) # eip
#endif
movl (__current), %eax
- movl 92(%eax), %eax
+ movl 64(%eax), %eax
test %eax, %eax # do we have stored x87 context?
jz 1f
popl %ebx # next
movl __current, %eax
- movl 88(%eax), %ecx # __current->pagetable
- movl 88(%ebx), %eax # next->pagetable
+ movl 60(%eax), %ecx # __current->pagetable
+ movl 60(%ebx), %eax # next->pagetable
cmpl %ecx, %eax # if(next->pagtable != __current->pagetable) {
jz 1f
{
__current->intr_ctx = *param;
- isr_param* lparam = &__current->intr_ctx;
+ struct exec_param* execp = __current->intr_ctx.execp;
- if (lparam->vector <= 255) {
- isr_cb subscriber = isrm_get(lparam->vector);
+ if (execp->vector <= 255) {
+ isr_cb subscriber = isrm_get(execp->vector);
subscriber(param);
goto done;
}
kprint_panic("INT %u: (%x) [%p: %p] Unknown",
- lparam->vector,
- lparam->err_code,
- lparam->cs,
- lparam->eip);
+ execp->vector,
+ execp->err_code,
+ execp->cs,
+ execp->eip);
done:
// for all external interrupts except the spurious interrupt
// this is required by Intel Manual Vol.3A, section 10.8.1 & 10.8.5
- if (lparam->vector >= IV_EX && lparam->vector != APIC_SPIV_IV) {
+ if (execp->vector >= IV_EX && execp->vector != APIC_SPIV_IV) {
apic_done_servicing();
}
void
__print_panic_msg(const char* msg, const isr_param* param)
{
+ struct exec_param* execp = param->execp;
kprint_panic(" INT %u: (%x) [%p: %p] %s",
- param->vector,
- param->err_code,
- param->cs,
- param->eip,
+ execp->vector,
+ execp->err_code,
+ execp->cs,
+ execp->eip,
msg);
}
goto segv_term;
}
- if (!SEL_RPL(param->cs)) {
+ if (!SEL_RPL(param->execp->cs)) {
// 如果是内核页错误……
if (do_kernel(&mapping)) {
return;
kprintf(KERROR "(pid: %d) Segmentation fault on %p (%p:%p)\n",
__current->pid,
ptr,
- param->cs,
- param->eip);
+ param->execp->cs,
+ param->execp->eip);
__SIGSET(__current->sig_pending, _SIGSEGV);
schedule();
// should not reach
proc0->intr_ctx = (isr_param){ .registers = { .ds = KDATA_SEG,
.es = KDATA_SEG,
.fs = KDATA_SEG,
- .gs = KDATA_SEG },
- .cs = KCODE_SEG,
- .eip = (void*)__proc0,
- .ss = KDATA_SEG,
- .eflags = cpu_reflags() };
+ .gs = KDATA_SEG } };
proc0->parent = proc0;
// 方案1:必须在读取eflags之后禁用。否则当进程被调度时,中断依然是关闭的!
VMAP_NULL);
}
- // 手动设置进程上下文:用于第一次调度
- asm volatile("movl %%esp, %%ebx\n"
- "movl %1, %%esp\n"
- "pushf\n"
- "pushl %2\n"
- "pushl %3\n"
- "pushl $0\n"
- "pushl $0\n"
- "movl %%esp, %0\n"
- "movl %%ebx, %%esp\n"
- : "=m"(proc0->intr_ctx.registers.esp)
- : "i"(KSTACK_TOP), "i"(KCODE_SEG), "r"(proc0->intr_ctx.eip)
- : "%ebx", "memory");
+ struct exec_param* execp =
+ (struct exec_param*)(KSTACK_TOP - sizeof(struct exec_param));
+
+ *execp = (struct exec_param){ .cs = KCODE_SEG,
+ .eip = (void*)__proc0,
+ .ss = KDATA_SEG,
+ .eflags = cpu_reflags() };
+ proc0->intr_ctx.execp = execp;
// 加载x87默认配置
asm volatile("fninit\n"
extern void my_dummy();
static char dummy_stack[DUMMY_STACK_SIZE] __attribute__((aligned(16)));
- // memset to 0
- dummy_proc = (struct proc_info){};
- dummy_proc.intr_ctx = (isr_param){
- .registers = { .ds = KDATA_SEG,
- .es = KDATA_SEG,
- .fs = KDATA_SEG,
- .gs = KDATA_SEG,
- .esp = (void*)dummy_stack + DUMMY_STACK_SIZE - 20 },
+ struct exec_param* execp =
+ (void*)dummy_stack + DUMMY_STACK_SIZE - sizeof(struct exec_param);
+
+ *execp = (struct exec_param){
.cs = KCODE_SEG,
+ .eflags = cpu_reflags() | 0x0200,
.eip = (void*)my_dummy,
.ss = KDATA_SEG,
- .eflags = cpu_reflags() | 0x0200
};
- *(u32_t*)(&dummy_stack[DUMMY_STACK_SIZE - 4]) = dummy_proc.intr_ctx.eflags;
- *(u32_t*)(&dummy_stack[DUMMY_STACK_SIZE - 8]) = KCODE_SEG;
- *(u32_t*)(&dummy_stack[DUMMY_STACK_SIZE - 12]) = dummy_proc.intr_ctx.eip;
+ // memset to 0
+ dummy_proc = (struct proc_info){};
+ dummy_proc.intr_ctx = (isr_param){ .registers = { .ds = KDATA_SEG,
+ .es = KDATA_SEG,
+ .fs = KDATA_SEG,
+ .gs = KDATA_SEG },
+ .execp = execp };
dummy_proc.page_table = cpu_rcr3();
dummy_proc.state = PS_READY;
由于这中间没有进行地址空间的交换,所以第二次跳转使用的是同一个内核栈,而之前默认tss.esp0的值是永远指向最顶部
这样一来就有可能会覆盖更早的上下文信息(比如嵌套的信号捕获函数)
*/
- tss_update_esp(proc->intr_ctx.registers.esp);
+ tss_update_esp(proc->intr_ctx.esp);
apic_done_servicing();