Skip to content

Commit 81cb6a0

Browse files
committed
aarch64: osi_linux fixes
1 parent b17fc23 commit 81cb6a0

File tree

2 files changed

+68
-38
lines changed

2 files changed

+68
-38
lines changed

panda/plugins/osi_linux/default_profile.cpp

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,53 +11,57 @@ target_ptr_t default_get_current_task_struct(CPUState *cpu)
1111
target_ptr_t current_task_addr;
1212
target_ptr_t ts;
1313

14-
#ifdef TARGET_ARM
14+
#ifdef TARGET_AARCH64
15+
extern target_ptr_t spel0;
1516
//aarch64
16-
if (((CPUARMState*) cpu->env_ptr)->aarch64) {
17-
//for kernel versions >= 4.10.0
18-
if(PROFILE_KVER_GE(ki, 4, 10, 0)) {
19-
current_task_addr = ki.task.init_addr;
20-
21-
//for kernel versions between 3.7.0 and 4.9.257
22-
} else if(PROFILE_KVER_LT(ki, 4, 10, 0) && PROFILE_KVER_GE(ki, 3, 7, 0)) {
23-
target_ptr_t kernel_sp = panda_current_ksp(cpu); //((CPUARMState*) cpu->env_ptr)->sp_el[1];
24-
target_ptr_t task_thread_info = kernel_sp & ~(0x4000-1);
25-
current_task_addr = task_thread_info+0x10;
26-
27-
28-
//because some kernel versions use both per_cpu variables AND access the task_struct
29-
//via the thread_info struct, the default call to struct_get with the per_cpu_offset_0_addr can be incorrect
30-
err = struct_get(cpu, &ts, current_task_addr, 0);
31-
assert(err == struct_get_ret_t::SUCCESS && "failed to get current task struct");
32-
fixupendian2(ts);
33-
return ts;
34-
} else {
35-
assert(false && "cannot use kernel version older than 3.7");
36-
}
37-
38-
//arm32
39-
} else {
40-
target_ptr_t kernel_sp = panda_current_ksp(cpu);
41-
42-
// XXX: This should use THREADINFO_MASK but that's hardcoded and wrong for my test system
43-
// We need to expose that as a part of the OSI config - See issue #651
44-
target_ptr_t task_thread_info = kernel_sp & ~(0x2000 -1);
45-
46-
//for kernel versions >= 5.18.0
47-
if (PROFILE_KVER_GE(ki, 5, 18, 0)) {
48-
return task_thread_info;
49-
}
50-
51-
current_task_addr=task_thread_info+0xC;
52-
17+
if (PROFILE_KVER_GE(ki, 4, 10, 0)){
18+
// https://elixir.bootlin.com/linux/v4.10/source/arch/arm64/include/asm/current.h#L25
19+
return spel0;
20+
} else if (PROFILE_KVER_GE(ki, 4, 6, 0)) {
21+
// untested
22+
// https://elixir.bootlin.com/linux/v4.6/source/arch/arm64/include/asm/thread_info.h#L79
23+
target_ptr_t task_thread_info = spel0;
24+
current_task_addr = task_thread_info+0x10;
25+
err = struct_get(cpu, &ts, current_task_addr, 0);
26+
return ts;
27+
} else if(PROFILE_KVER_GE(ki, 3, 7, 0)) {
28+
// https://elixir.bootlin.com/linux/v3.7/source/arch/arm64/include/asm/thread_info.h#L79
29+
target_ptr_t kernel_sp = panda_current_ksp(cpu); //((CPUARMState*) cpu->env_ptr)->sp_el[1];
30+
target_ptr_t task_thread_info = kernel_sp & ~(0x4000-1);
31+
current_task_addr = task_thread_info+0x10;
5332
//because some kernel versions use both per_cpu variables AND access the task_struct
5433
//via the thread_info struct, the default call to struct_get with the per_cpu_offset_0_addr can be incorrect
5534
err = struct_get(cpu, &ts, current_task_addr, 0);
5635
assert(err == struct_get_ret_t::SUCCESS && "failed to get current task struct");
5736
fixupendian2(ts);
5837
return ts;
38+
} else {
39+
// solid chance the above implemntation just works for older kernels
40+
// see: https://elixir.bootlin.com/linux/v2.6.39.4/source/arch/arm/include/asm/thread_info.h#L92
41+
assert(false && "cannot use kernel version older than 3.7");
42+
}
43+
#elif defined(TARGET_ARM) && !defined(TARGET_AARCH64)
44+
//arm32
45+
target_ptr_t kernel_sp = panda_current_ksp(cpu);
5946

47+
// XXX: This should use THREADINFO_MASK but that's hardcoded and wrong for my test system
48+
// We need to expose that as a part of the OSI config - See issue #651
49+
target_ptr_t task_thread_info = kernel_sp & ~(0x2000 -1);
50+
51+
//for kernel versions >= 5.18.0
52+
if (PROFILE_KVER_GE(ki, 5, 18, 0)) {
53+
return task_thread_info;
6054
}
55+
56+
current_task_addr=task_thread_info+0xC;
57+
58+
//because some kernel versions use both per_cpu variables AND access the task_struct
59+
//via the thread_info struct, the default call to struct_get with the per_cpu_offset_0_addr can be incorrect
60+
err = struct_get(cpu, &ts, current_task_addr, 0);
61+
assert(err == struct_get_ret_t::SUCCESS && "failed to get current task struct");
62+
fixupendian2(ts);
63+
return ts;
64+
6165
#elif defined(TARGET_MIPS)
6266
// __current_thread_info is stored in KERNEL r28
6367
// userspace clobbers it but kernel restores (somewhow?)

panda/plugins/osi_linux/osi_linux.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,19 @@ inline bool can_read_current(CPUState *cpu) {
349349
// won't check again until the first syscall.
350350
bool r28_set = false;
351351
inline void check_cache_r28(CPUState *cpu);
352+
#elif TARGET_AARCH64
353+
354+
target_ulong spel0 = 0;
355+
bool aarch64_initialized = false;
356+
357+
void aarch64_sbe(CPUState *cpu, TranslationBlock *tb);
358+
void aarch64_sbe(CPUState *cpu, TranslationBlock *tb) {
359+
if (unlikely(panda_in_kernel_code_linux(cpu) && ((CPUARMState*) cpu->env_ptr)->sp_el[0] != 0)){
360+
aarch64_initialized = true;
361+
spel0 = ((CPUARMState*) cpu->env_ptr)->sp_el[0];
362+
}
363+
}
364+
352365
#endif
353366

354367
/**
@@ -379,6 +392,13 @@ bool osi_guest_is_ready(CPUState *cpu, void** ret) {
379392
return false;
380393
}
381394
}
395+
#elif defined(TARGET_AARCH64)
396+
if (PROFILE_KVER_GE(ki, 4, 6, 0)){
397+
if (!aarch64_initialized){
398+
*ret = NULL;
399+
return false;
400+
}
401+
}
382402
#endif
383403
first_osi_check = false;
384404

@@ -1315,6 +1335,12 @@ bool init_plugin(void *self) {
13151335
notify_task_change(cpu);
13161336
} });
13171337

1338+
#ifdef TARGET_AARCH64
1339+
if (PROFILE_KVER_GE(ki, 4, 6, 0)){
1340+
panda_cb pcb = { .start_block_exec = aarch64_sbe };
1341+
panda_register_callback(self, PANDA_CB_START_BLOCK_EXEC, pcb);
1342+
}
1343+
#endif
13181344
return true;
13191345
#else
13201346
fprintf(stderr, PLUGIN_NAME "Unsupported guest architecture\n");

0 commit comments

Comments
 (0)