Bug 982 - Support PowerPC ABI in ISACaller
Summary: Support PowerPC ABI in ISACaller
Status: RESOLVED FIXED
Alias: None
Product: Libre-SOC's first SoC
Classification: Unclassified
Component: Source Code (show other bugs)
Version: unspecified
Hardware: PC Linux
: High enhancement
Assignee: Jacob Lifshay
URL:
Depends on: 1173
Blocks: 1168 1169
  Show dependency treegraph
 
Reported: 2022-12-08 18:44 GMT by Dmitry Selyutin
Modified: 2024-01-16 09:45 GMT (History)
6 users (show)

See Also:
NLnet milestone: NLnet.2021-08-071.cavatools
total budget (EUR) for completion of task and all subtasks: 4500
budget (EUR) for this task, excluding subtasks' budget: 4500
parent task for budget allocation: 939
child tasks for budget allocation:
The table of payments (in EUR) for this task; TOML format:
ghostmansd = { amount = 2200, submitted = 2023-10-26, paid = 2023-11-13 } lkcl = { amount = 1300, submitted = 2023-11-04, paid = 2023-11-24 } [jacob] amount = 1000 submitted = 2024-01-05 paid = 2024-01-12


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dmitry Selyutin 2022-12-08 18:44:27 GMT
We need to maintain the reference Python simulator, which also lacks proper userspace ABI support. The ABI support is essential for running real userspace applications.

--

* https://github.com/qemu/qemu/blob/master/linux-user/syscall.c
Comment 1 Andrey Miroshnikov 2023-09-05 11:53:31 BST
Reassigning this bug to me (with Shriya cc'd so she can study along).

From my understanding of the task, the actual work would require:

- In ISACaller, parse the 'sc' (system call) PowerISA instruction and extract the system call number argument.

- Import relevant library into Python which allows to make system calls.

- Look up PowerISA ABI, to see which system call arguments correspond to open()/read)()/write() (the system calls chosen for the scope of this task).

- Extend the ISACaller (with if-elif-else type of block) which will make the relevant system call depending on the 'sc' instruction argument.

The hardest part of the task seems to me to be understanding where to modify the ISACaller simulator, so I'll begin by making sure I can run example programs with it (and make a modified binary which includes a system call instruction).
Comment 2 Jacob Lifshay 2023-09-05 16:57:31 BST
note that the list of actual syscalls that are needed to run a simple program are a bit different:
I tested the following program on ppc64le:
gcc -x c - -static <<'EOF'
#include <stdio.h>
int main() {
    FILE *f;
    f = fopen("/proc/cmdline", "r");
    if(!f) return 1;
    while(1) {
        int ch = fgetc(f);
        if(ch == EOF) break;
        putchar(ch);
    }
    int err = ferror(f);
    fclose(f);
    return err ? 1 : 0;
}
EOF

actual syscalls (ignore the initial execve):
strace ./a.out
execve("./a.out", ["./a.out"], 0x7fffed38eae0 /* 18 vars */) = 0
brk(NULL)                               = 0x1000c670000
brk(0x1000c670fe4)                      = 0x1000c670fe4
uname({sysname="Linux", nodename="75-224-155-23", ...}) = 0
readlink("/proc/self/exe", "/home/jacob/a.out", 4096) = 17
brk(0x1000c6a0fe4)                      = 0x1000c6a0fe4
brk(0x1000c6b0000)                      = 0x1000c6b0000
openat(AT_FDCWD, "/proc/cmdline", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
read(3, "root=UUID=0ff31a9e-7434-4c47-b03"..., 1024) = 86
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}) = 0
write(1, "root=UUID=0ff31a9e-7434-4c47-b03"..., 86root=UUID=0ff31a9e-7434-4c47-b030-502a14729112 ro quiet disable_radix init=/sbin/init
) = 86
read(3, "", 1024)                       = 0
close(3)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

so, the list that needs is:
brk
uname
readlink
openat
fstat
read
write
close
exit_group
Comment 3 Jacob Lifshay 2023-09-05 17:13:38 BST
note that this doesn't need to change the list of syscalls you've chosen to implement, just that they aren't all necessarily the most useful ones.

(In reply to Jacob Lifshay from comment #2)
> so, the list that needs is:
> brk
for dynamic memory allocation and/or dynamic linking, mmap and munmap are also useful.
> uname
if you implement uname, it will need to return results you'd expect on a ppc64le system, not whatever the python script is running on.
> readlink
> openat
> fstat
> read
> write
> close
> exit_group
this needs to *not* call the exit syscall, but instead just stop the simulator.
Comment 4 Luke Kenneth Casson Leighton 2023-09-05 17:58:25 BST
(In reply to Jacob Lifshay from comment #2)
> note that the list of actual syscalls that are needed to run a simple
> program are a bit different:
> I tested the following program on ppc64le:
> gcc -x c - -static <<'EOF'
> #include <stdio.h>
> int main() {
>     FILE *f;
>     f = fopen("/proc/cmdline", "r");

it's very important to avoid fopen at the early phase, and just do
read open write and close.  ("man 2 open")

check the size of the binary (static compile, stripped) and it will be
obvious why, immediately.

fopen pulls in vast quantities of libc6 including threads locking
spinlocks mutexes, it's a whole stack of shit that massively raises
the initial starting-point to an overwhelming barrier, *and* you
end up running hundreds of thousands of unnecessary instructions
to even initilise all that shit.

you don't need the hassle. cut the bullshit, make life easy, do the
other syscalls later.

btw there is a *REAL* simple way to get this entire thing done
*REAL* fast:

https://stackoverflow.com/questions/37032203/make-syscall-in-python

if you trap malloc realloc and free and emulate them (there are
plenty of "replacement" libraries which do exactly this)
then this entire job is done in about... ooo... a week?

on that: i don't want to hear anyone say "But Security"
or "But Guest interference with Host???" - this is not
qemu, this is an expedient simulator trick, deployed by
cavatools to achieve 500 to 1,000 times the speed of e.g.
risc-v-spike simulator.
Comment 5 Luke Kenneth Casson Leighton 2023-09-05 18:13:11 BST
(In reply to Andrey Miroshnikov from comment #1)
> Reassigning this bug to me (with Shriya cc'd so she can study along).
> 
> From my understanding of the task, the actual work would require:
> 
> - In ISACaller, parse the 'sc' (system call) PowerISA instruction and
> extract the system call number argument.

r3 i think you'll find. check the disasm on a simple binary using
open() write() and close().


> - Import relevant library into Python which allows to make system calls.

which you may need to write.

> - Look up PowerISA ABI, to see which system call arguments correspond to
> open()/read)()/write() (the system calls chosen for the scope of this task).

been in the media/ directory for 3 years now, and how syscalls work
i think i found links online. basically they are exactly
the same as a function (set up regs) but instead of "branch to address"
you do "sc".

https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=media/calling-conv;hb=HEAD


> - Extend the ISACaller (with if-elif-else type of block) which will make the
> relevant system call depending on the 'sc' instruction argument.

just write a unit test that calls one instruction: "sc".
then see what happens.

> The hardest part of the task seems to me to be understanding where to modify
> the ISACaller simulator, so I'll begin by making sure I can run example
> programs with it (and make a modified binary which includes a system call
> instruction).

no: just write *one* unit test with *one* instruction in it (sc).
do not attempt to use pypowersim on the initial phase.
that comes later once *even one* system call has been verifed
by at least one unit test (each).

you know the drill, you know how python projects work (unit tests,
unit tests, unit tests), you know how that online "word game" works
("what tiny steps get me from Word ABCD to word XYZW").

going directly to pypowersim is *clearly* too much with zero intermediary
steps that will utterly overwhelm you, when you know next to nothing
about the details involved, so why even attempt it?

therefore logically it is your responsibility to work out the tiny
intermediary steps. can i please not be put into a position of having
to remind you of this again given that i have repeated it so many
times already? i will assume that i do not need to say this again.
Comment 6 Jacob Lifshay 2023-09-05 18:20:35 BST
(In reply to Luke Kenneth Casson Leighton from comment #4)
> (In reply to Jacob Lifshay from comment #2)
> > note that the list of actual syscalls that are needed to run a simple
> > program are a bit different:
> > I tested the following program on ppc64le:
> > gcc -x c - -static <<'EOF'
> > #include <stdio.h>
> > int main() {
> >     FILE *f;
> >     f = fopen("/proc/cmdline", "r");
> 
> it's very important to avoid fopen at the early phase, and just do
> read open write and close.  ("man 2 open")

that doesn't help much:
strace ./a.out > out.txt
execve("./a.out", ["./a.out"], 0x7fffed669f60 /* 18 vars */) = 0
brk(NULL)                               = 0x1001a000000
brk(0x1001a000fe4)                      = 0x1001a000fe4
uname({sysname="Linux", nodename="75-224-155-23", ...}) = 0
readlink("/proc/self/exe", "/home/jacob/a.out", 4096) = 17
brk(0x1001a030fe4)                      = 0x1001a030fe4
brk(0x1001a040000)                      = 0x1001a040000
openat(AT_FDCWD, "/proc/cmdline", O_RDONLY|O_CLOEXEC) = 3
read(3, "root=UUID=0ff31a9e-7434-4c47-b03"..., 4096) = 86
write(1, "root=UUID=0ff31a9e-7434-4c47-b03"..., 86) = 86
read(3, "", 4096)                       = 0
exit_group(0)                           = ?
+++ exited with 0 +++


I used this program:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>

#define BUFSZ 4096

#define RETRY_SYSCALL(retval, call) \
do { \
    retval = (call); \
} while(retval == -1 && errno == EINTR)

int main() {
    unsigned char buf[BUFSZ];
    int fd;
    RETRY_SYSCALL(fd, open("/proc/cmdline", O_RDONLY | O_CLOEXEC));
    if(fd == -1)
        return 1;

    while(1) {
        ssize_t read_count;
        RETRY_SYSCALL(read_count, read(fd, buf, sizeof(buf)));
        if(read_count == -1)
            return 1;
        if(read_count == 0)
            break;
        ssize_t pos = 0;
        while(pos < read_count) {
            ssize_t write_count, left = read_count - pos;
            RETRY_SYSCALL(write_count, write(STDOUT_FILENO, &buf[pos], left));
            if(write_count == -1)
                return 1;
            pos += write_count;
        }
    }

    // close(fd);

    return 0;
}
Comment 7 Luke Kenneth Casson Leighton 2023-09-05 19:44:44 BST
(In reply to Jacob Lifshay from comment #6)

still too complex.

 
> #define RETRY_SYSCALL(retval, call) \
> do { \
>     retval = (call); \
> } while(retval == -1 && errno == EINTR)

cut this
 
> int main() {
>     unsigned char buf[BUFSZ];
>     int fd;
>     RETRY_SYSCALL(fd, open("/proc/cmdline", O_RDONLY | O_CLOEXEC));

cut macro.

>     if(fd == -1)
>         return 1;

cut. assume success.

>     while(1) {

cut loop

>         ssize_t read_count;
>         RETRY_SYSCALL(read_count, read(fd, buf, sizeof(buf)));

cut macro

>         ssize_t pos = 0;
>         while(pos < read_count) {

cut loop

>             ssize_t write_count, left = read_count - pos;
>             RETRY_SYSCALL(write_count, write(STDOUT_FILENO, &buf[pos],
> left));

cut macro

>             if(write_count == -1)
>                 return 1;

cut.  assume success

>             pos += write_count;

cut. assume write amount is same as read amount

now that's down to a manageable easy program that when disassembled
is blindingly-obvious, and could easily fit into a VERY SHORT
test_caller_sc_***.py unit test.

do learn to stop making "perfect" the enemy of "good enough".
your experience and preference for rust is hampering delivery
and costing you (and the team) money that they could earn far
quicker.

a *second* unit test - under pypowersim - would be to run
the program that you wrote, as a way to test expected error conditions,
but that is *optional*... after everything else has been done,
and likely there are some libc6 unit tests that could drop in
here (cross-ref to NGI Search Grant) bug #1106 bug #1109
Comment 8 Jacob Lifshay 2023-09-05 22:41:05 BST
(In reply to Luke Kenneth Casson Leighton from comment #7)
> (In reply to Jacob Lifshay from comment #6)
> 
> still too complex.

my point is that the actual syscalls strace reports don't match the functions I'm calling. Ignore the C program complexity, it's just a short demo.
Comment 9 Jacob Lifshay 2023-09-05 22:45:19 BST
(In reply to Jacob Lifshay from comment #8)
> (In reply to Luke Kenneth Casson Leighton from comment #7)
> > (In reply to Jacob Lifshay from comment #6)
> > 
> > still too complex.
> 
> my point is that the actual syscalls strace reports don't match the
> functions I'm calling. Ignore the C program complexity, it's just a short
> demo.

oh, and also that there are a bunch of syscalls called by glibc's init code before main -- the brk and uname and readlink calls
Comment 10 Luke Kenneth Casson Leighton 2023-09-05 22:47:05 BST
(In reply to Jacob Lifshay from comment #8)

> my point is that the actual syscalls strace reports don't match the
> functions I'm calling. Ignore the C program complexity, it's just a short
> demo.

ah - ok i get it.  use strace -ff -o xxxx.out, it separates each
process by PID.

openat instead of open is a new one on me.

exit_group is likely bash.  -ff will get you *only* what the a.out
actually does, in its own xxxx.out.PID file
Comment 11 Jacob Lifshay 2023-09-05 22:51:36 BST
(In reply to Luke Kenneth Casson Leighton from comment #10)
> (In reply to Jacob Lifshay from comment #8)
> 
> > my point is that the actual syscalls strace reports don't match the
> > functions I'm calling. Ignore the C program complexity, it's just a short
> > demo.
> 
> ah - ok i get it.  use strace -ff -o xxxx.out, it separates each
> process by PID.

afaict that is all only a.out, bash is not included.
> 
> openat instead of open is a new one on me.
> 
> exit_group is likely bash.

exit_group is caused by returning from main and then the startup code calls exit, which uses the exit_group syscall
Comment 12 Jacob Lifshay 2023-09-05 22:56:56 BST
(In reply to Jacob Lifshay from comment #11)
> (In reply to Luke Kenneth Casson Leighton from comment #10)
> > ah - ok i get it.  use strace -ff -o xxxx.out, it separates each
> > process by PID.

ok, tried: strace -ff -o out.txt ./a.out

out.txt.71212:
execve("./a.out", ["./a.out"], 0x7fffeb4d7bb8 /* 18 vars */) = 0
brk(NULL)                               = 0x10037460000
brk(0x10037460fe4)                      = 0x10037460fe4
uname({sysname="Linux", nodename="75-224-155-23", ...}) = 0
readlink("/proc/self/exe", "/home/jacob/a.out", 4096) = 17
brk(0x10037490fe4)                      = 0x10037490fe4
brk(0x100374a0000)                      = 0x100374a0000
openat(AT_FDCWD, "/proc/cmdline", O_RDONLY|O_CLOEXEC) = 3
read(3, "root=UUID=0ff31a9e-7434-4c47-b03"..., 4096) = 86
write(1, "root=UUID=0ff31a9e-7434-4c47-b03"..., 86) = 86
read(3, "", 4096)                       = 0
exit_group(0)                           = ?
+++ exited with 0 +++
Comment 13 Luke Kenneth Casson Leighton 2023-09-06 00:29:30 BST
(In reply to Jacob Lifshay from comment #12)
> (In reply to Jacob Lifshay from comment #11)
> > (In reply to Luke Kenneth Casson Leighton from comment #10)
> > > ah - ok i get it.  use strace -ff -o xxxx.out, it separates each
> > > process by PID.
> 
> ok, tried: strace -ff -o out.txt ./a.out

intriguing - no change... analysing:

> out.txt.71212:
> execve("./a.out", ["./a.out"], 0x7fffeb4d7bb8 /* 18 vars */) = 0

request to replace the current process by this one. whyy...
ohh you're not running grsecurity or se/linux or anything,
are you?

> brk(NULL)                               = 0x10037460000
> brk(0x10037460fe4)                      = 0x10037460fe4
> uname({sysname="Linux", nodename="75-224-155-23", ...}) = 0
> readlink("/proc/self/exe", "/home/jacob/a.out", 4096) = 17
> brk(0x10037490fe4)                      = 0x10037490fe4
> brk(0x100374a0000)                      = 0x100374a0000

hmmm... yes agreed, likely libc6 initialisation.

> openat(AT_FDCWD, "/proc/cmdline", O_RDONLY|O_CLOEXEC) = 3
> read(3, "root=UUID=0ff31a9e-7434-4c47-b03"..., 4096) = 86
> write(1, "root=UUID=0ff31a9e-7434-4c47-b03"..., 86) = 86
> read(3, "", 4096)                       = 0

expected

> exit_group(0)                           = ?

why exit_group - weird. i wonder if it's due to something
recent in libc6 and/or threading being enabled for some
reason.

it'd be good to get down to a minimum program... it's still massive
(due to whole unnecessary chunks of libc6 being dragged in, sigh)

----

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char *argv[] ) {
    int fd = open("/tmp/x", O_CREAT, S_IRUSR);
    write(fd, "hello", 5);
    return 0;
}

----

$ history
  ...
  589  powerpc64-linux-gnu-gcc -static -static-libgcc open.c
  590  objdump -D a.out  > /tmp/x
  ...
Comment 14 Luke Kenneth Casson Leighton 2023-09-06 00:44:03 BST
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char *argv[] ) {
    write(1, "hello\n", 6);
    return 0;
}

==>

0000000010000974 <.main>:
    10000974:   7c 08 02 a6     mflr    r0
    10000978:   f8 01 00 10     std     r0,16(r1)
    1000097c:   fb e1 ff f8     std     r31,-8(r1)
    10000980:   f8 21 ff 81     stdu    r1,-128(r1)
    10000984:   7c 3f 0b 78     mr      r31,r1
    10000988:   7c 69 1b 78     mr      r9,r3
    1000098c:   f8 9f 00 b8     std     r4,184(r31)
    10000990:   91 3f 00 b0     stw     r9,176(r31)
    10000994:   38 a0 00 06     li      r5,6
    10000998:   3c 82 ff fb     addis   r4,r2,-5
    1000099c:   38 84 76 68     addi    r4,r4,30312
    100009a0:   38 60 00 01     li      r3,1
    100009a4:   48 02 16 1d     bl      10021fc0 <.__libc_write>
    100009a8:   60 00 00 00     nop
    100009ac:   39 20 00 00     li      r9,0
    100009b0:   7d 23 4b 78     mr      r3,r9
    100009b4:   38 3f 00 80     addi    r1,r31,128
    100009b8:   e8 01 00 10     ld      r0,16(r1)
    100009bc:   7c 08 03 a6     mtlr    r0
    100009c0:   eb e1 ff f8     ld      r31,-8(r1)
    100009c4:   4e 80 00 20     blr
    100009c8:   00 00 00 00     .long 0x0
    100009cc:   00 00 00 01     .long 0x1
    100009d0:   80 01 00 01     lwz     r0,1(r1)
    100009d4:   60 00 00 00     nop
    100009d8:   60 00 00 00     nop
    100009dc:   60 00 00 00     nop

and i bet you if you replace that "bl __libc_write" with "sc"
directly in assembler you'll end up with "hello" on the terminal.
Comment 15 Luke Kenneth Casson Leighton 2023-09-06 01:03:00 BST
okaaaay fiiinallyyy, found one.

https://github.com/matja/asm-examples/blob/master/ppc64/hello.ppc64.linux.syscall.gas.asm

message:
	.ascii "Hello world!\n"

._start:
	li     0, 4 # syscall 4 - write
	li     3, 1 # arg 0 - fd = 1 (stdout)
	lis    4, message@highest # arg 1 - buffer
	ori    4, 4, message@higher
	rldicr 4, 4, 32, 31
	oris   4, 4, message@h
	ori    4, 4, message@l
	li     5, message_length # arg 2 - size
	sc     # do syscall

	li     0, 1 # syscall 1 - exit
	li     3, 0 # arg 0 - exit code = 0
	sc     # do syscall
Comment 16 Andrey Miroshnikov 2023-09-06 19:56:57 BST
Thanks very much to both of you for your findings.

Luke's comments in the IRC log:
https://libre-soc.org/irclog/%23libre-soc.2023-09-06.log.html#t2023-09-06T15:01:08

mention how 'write' systemcall can be used with hello world to stdout example (demonstrated on qemu-ppc64le-user). I will replicate this and continue with the task later this week.
Comment 17 Luke Kenneth Casson Leighton 2023-09-06 20:08:54 BST
(In reply to Andrey Miroshnikov from comment #16)
> Thanks very much to both of you for your findings.
> 
> Luke's comments in the IRC log:
> https://libre-soc.org/irclog/%23libre-soc.2023-09-06.log.html#t2023-09-06T15:
> 01:08
> 
> mention how 'write' systemcall can be used with hello world to stdout
> example 

comment #15. commands at top of file. prefix with ppc64le-linux-gnu-

> (demonstrated on qemu-ppc64le-user).

https://wiki.debian.org/QemuUserEmulation

very useful.

when pypowersim has ELF support it should also work via foreign binfmt.
Comment 18 Andrey Miroshnikov 2023-09-13 19:57:09 BST
(In reply to Luke Kenneth Casson Leighton from comment #17)
>
> https://wiki.debian.org/QemuUserEmulation
> 
> very useful.

Thanks, I was able to assemble and run the example (using qemu).


Found another hello world assembler example (which actually explained what @highest, @higher, @h, @l meant):
https://gist.github.com/sandip4n/09b50786e88968faaecdf42360c85b1b
(otherwise the assembler is exactly the same)

I created a basic unit test which only calls the system call 'sc' instruction (with reg's preloaded).
https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=1be8996cbea4d5bcb96ed9a91c2f0dbfcacf7ee1
https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=2c075be04e5603ffb161002a99e4684b41973829

I entered the expected values as per sc instruction definition in PowerISA v3.1b, Book III, Chapter 4, section 4.3.1 System Linkage Instructions:
SRR0 <- i_ea CIA + 4
SRR1_33:36 42:47 <- 0
SRR1_0:32 37:41 48:63 <- MSR_0:32 37:41 48:63
MSR <- new_value (see below)
NIA <- 0x0000_0000_0000_0C00

The MSR value is defined in Section 7.5 (same book), figure 69.
NIA comes from figure 70.

The Libre-SOC pseudo-code looks similar:
SRR0 <-iea CIA + 4
SRR1[33:36] <- 0
SRR1[42:47] <- 0
SRR1[0:32]  <- MSR[0:32]
SRR1[37:41] <- MSR[37:41]
SRR1[48:63] <- MSR[48:63]
MSR <- new_value
NIA <- 0x0000_0000_0000_0C00


Running the test_caller_syscall.py causes the following assertions to fail (need to set e.pc to value given by simulator to get other assertion errors):

AssertionError: 0x0 != 0x8: SPR.SRR0 mismatch (sim != expected) 'sc'
My understanding (based on pseudo-code from PowerISA spec and Libre-SOC page), is that SRR0 will be equal to CIA+4.
At the start of the program I defined cia (pc) as 4, so 8 should be the expected value. Is the simulator not setting SRR0 at all?

AssertionError: 0x9000000000082903 != 0x9000000000002903: SPR.SRR1 mismatch (sim != expected) 'sc'
SRR1 is equal to the MSR before the syscall is made, in this case default value of 0x9000000000002903 was used. Seems like bit 19 is set (where that 8 is).

AssertionError: 1792 != 3072 : pc mismatch (sim != expected) 'sc'
I picked 3072 (0xC00) as I wasn't sure what it's going to be.
However it doesn't make sense where 1792 (0x700) comes from.

Not sure how to proceed (other than digging through the internals of ISACaller). Am I making an endian-ness error?
Comment 19 Luke Kenneth Casson Leighton 2023-09-13 22:13:11 BST
(In reply to Andrey Miroshnikov from comment #18)

> At the start of the program I defined cia (pc) as 4, 

which will attempt to execute the *second* instruction in the
list, which of course you don't have.

you need to actually look at the trace output closely, and at caller.py
searching for log(...) and linking the two in your mind.

then you can follow what the simulator is actually doing.

you remember i said "you need to be very very patient" and you
replied "i don't think i can do that"?  sorry to have to repeat it:
you need to be very very patient. slow down, pay attention, and think
like a simulator.

the program unless told otherwise is loaded into "memory" location
0x0000_0000_0000_0000.

you *can* specify otherwise, but very few unit tests do that and i
haven't used the option to ISACaller in over a year, you'll have to
hunt for it yourself....

... or just don't try setting the start pc to 0x4, it is non-standard
for the unit tests anyway. doable but non-standard.
Comment 20 Andrey Miroshnikov 2023-09-13 22:18:36 BST
(In reply to Luke Kenneth Casson Leighton from comment #19)
> > At the start of the program I defined cia (pc) as 4, 
> 
> which will attempt to execute the *second* instruction in the
> list, which of course you don't have.

For some reason I find this pretty cool.
If I didn't copy a test that had several instructions, may not have stumbled upon this so quickly.

> 
> you need to actually look at the trace output closely, and at caller.py
> searching for log(...) and linking the two in your mind.
> 
> then you can follow what the simulator is actually doing.

Thanks, will do.

> the program unless told otherwise is loaded into "memory" location
> 0x0000_0000_0000_0000.
> 
> you *can* specify otherwise, but very few unit tests do that and i
> haven't used the option to ISACaller in over a year, you'll have to
> hunt for it yourself....
> 
> ... or just don't try setting the start pc to 0x4, it is non-standard
> for the unit tests anyway. doable but non-standard.

Will keep in mind. Trying the standard way makes sense first.
Comment 21 Luke Kenneth Casson Leighton 2023-09-13 23:01:26 BST
(In reply to Andrey Miroshnikov from comment #20)

> Will keep in mind. Trying the standard way makes sense first.

(look at some of the virtual memory tests and the trap tests,
 they do weird stuff inclucing passing a "stop if PC=0x700"
 parameter. a LOT has been incrementallyndone in 3 years, it
 is extremely sophisticated).
Comment 22 Jacob Lifshay 2023-09-14 03:46:55 BST
Andrey, while I was reading the code you wrote:
https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/test/syscall/syscall_cases.py;h=2e64315833810a7c38ee9733cba1e9e04e38ceeb;hb=1be8996cbea4d5bcb96ed9a91c2f0dbfcacf7ee1#l38

you need to pass a pointer to the bytes to the write syscall, not put the bytes directly in the register.

so, to write data to memory, do:
initial_mem = {}
base_addr = 0x10000  # arbitrarily selected, must not overlap something else
for idx, v in enumerate(the_bytes):
    # write v as 1 byte at address idx + base_addr
    initial_mem[idx + base_addr] = v, 1
initial_regs[4] = base_addr  # pointer to start of data we just wrote
...
self.add_case(self.program, initial_regs, initial_mem=initial_mem, ...)

for an example, see:
https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/test/algorithms/svp64_utf_8_validation.py;h=054fd481dab0040dcb302f0506ab04bc8b52c864;hb=1be8996cbea4d5bcb96ed9a91c2f0dbfcacf7ee1#l352

in the example, note that those *_LUT constants are lists of enums, hence why I used int(v) to convert them before assigning to initial_mem
Comment 23 Luke Kenneth Casson Leighton 2023-09-14 07:57:14 BST
(In reply to Jacob Lifshay from comment #22)
> Andrey, while I was reading the code you wrote:
> https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/test/
> syscall/syscall_cases.py;h=2e64315833810a7c38ee9733cba1e9e04e38ceeb;
> hb=1be8996cbea4d5bcb96ed9a91c2f0dbfcacf7ee1#l38
> 
> you need to pass a pointer to the bytes to the write syscall, not put the
> bytes directly in the register.

yes. this is exactly a function call (just with r0={thesystemcallnumber}
therefore, you need to read the man page:
    https://man7.org/linux/man-pages/man2/write.2.html

note that the header is:
    ssize_t write(int fd, const void buf[.count], size_t count);

read the ABI dcument calling convention:
    https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=media/calling-conv;hb=HEAD

and set r3=fd (stdout) r4=*ADDRESS* of buf r5=count.

can i suggest putting the above links and some explanatory comments
into the code so that it can be referred to as a way to help guide
people on syscalls?


also: every single file *MUST* have:

* Copyright notices (including the original if you copied contents 
  of the file from somewhere)
* License Header (SPDX)
* Thank you to NLnet and the associated EU Grant.

all of that is MANDATORY for the project.

also in this case put the bug URL to crossref here.
Comment 24 Jacob Lifshay 2023-09-15 23:06:52 BST
(In reply to Luke Kenneth Casson Leighton from comment #23)
> note that the header is:
>     ssize_t write(int fd, const void buf[.count], size_t count);

on my computer that's (imho easier to read since it doesn't use obscure C features):

ssize_t write(int fd, const void *buf, size_t count);
Comment 25 Luke Kenneth Casson Leighton 2023-09-15 23:55:49 BST
(In reply to Jacob Lifshay from comment #24)

> (imho

please do stop saying "in my HUMBLE opinion": i did say
it is irritating and unnecessary in a goal-orientated
non-ego-driven team.

> easier to read since it doesn't use obscure C
> features):
> 
> ssize_t write(int fd, const void *buf, size_t count);

i cut/paste what is straight out of the online man page,
and yes it is somewhat dismaying to see these "improvements"
from doing c since 1989.  ultimately though, the "types"
get utterly ignored at the low level of regs: all safety-nets
(e.g. const) are out the window.
Comment 26 Luke Kenneth Casson Leighton 2023-09-16 08:30:05 BST
https://github.com/qemu/qemu/blob/master/linux-user/syscall.c

this - all twelve THOUSAND lines - is what qemu-user does to
emulate systemcalls [safely].

the fact that "memory" is emulated means that when it comes
for example to emulate write() it is necessary to extract
the contents of sim.mem at the appropriate "address",
to place it into a suitable buffer (of size count) and
then pass **that** buffer to (either) an actual syscall
(or a write function call that ultimately ends up calling
that syscall on your behalf).
Comment 27 Luke Kenneth Casson Leighton 2023-09-17 19:10:54 BST
https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=48ec1783c5

dmitry i love the idea of an autogenerated table, however we have a
hard rule (in HDL_workflow wiki page since the inception of the project)
that no autogenerated output shall be committed to the repository.

can you please remove it and either create it "on-demand" (see python-ply
for that trick) or just use/adapt the autogenerator *itself*, or add
a Makefile target (similar to "make pywriter") which will then also
need adding to devscripts.

l.
Comment 28 Dmitry Selyutin 2023-09-17 19:19:06 BST
OK, I made a start on system calls mapping:

https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=74ea3c42bef943da263395d19c50ad4dba605b9f

There's a tool which parses the Linux kernel tree and obtains all system calls available, considering the ABI and other stuff. The only argument is the path to the Linux kernel source code. An example of how its output looks like (beware, huge!):

https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=48ec1783c5f7cc64629fba65575db2d3881e8026

I committed this since we're unlikely to take Linux kernel with us. Linux keeps userspace ABI stable (ugly but stable). So the situation we need to generate again is unlikely to happen. Note that this is an exception I committed this artifact: I don't usually do it, it's a bad practice, terrible and even disasterous things can happen.


How do you use it?

>>> syscall_id = 286 # some deliberate example
>>> from openpower.syscalls import tables
>>> (name, entries) = tables.SYSNUMS["ppc"]["common"][str(syscall_id)]
>>> print(name, entries)
openat ['sys_openat', 'compat_sys_openat']
>>> native = int(tables.SYSNUMS["x86-64"]["common"][name])
>>> print(native)
257
>>> print(tables.SYSARGS[name])
{'dfd': 'int', 'filename': 'const char __user *', 'flags': 'int', 'mode': 'umode_t'}


I suppose this should be sufficient to start playing with mapping emulated PPC system calls to architecture the simulator runs on. Beware, SYSARGS table, as well as entries upon lookup, are here for a reason: different architectures pass arguments differently (ditto pipe, compat_arg_u64_dual and similar stuff).
Linux vaunted userspace ABI is a gory mess.


What's missing here?
1. Host architecture detection, including "running 32-bit code on 64-bit architecture" (not sure whether we need it though).
2. Logic for looking into different ABIs (e.g. some system calls might not be in "common" ABI section).
3. The actual call redirection. This is easy enough, because libc already has a shim "syscall". As long as the arguments match each other on two hosts, obviously. Otherwise there must be a bunch of "special cases" and "let's inspect the arguments logic".
Comment 29 Dmitry Selyutin 2023-09-17 19:23:53 BST
(In reply to Luke Kenneth Casson Leighton from comment #27)
> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=48ec1783c5
> 
> dmitry i love the idea of an autogenerated table, however we have a
> hard rule (in HDL_workflow wiki page since the inception of the project)
> that no autogenerated output shall be committed to the repository.
> 
> can you please remove it and either create it "on-demand" (see python-ply
> for that trick) or just use/adapt the autogenerator *itself*, or add
> a Makefile target (similar to "make pywriter") which will then also
> need adding to devscripts.
> 
> l.

You were faster than me. :-) Yes this is a totally ugly practice, I'll drop it. That's for illustrative purposes. What'd be the right place and way to download the Linux kernel? I'm sure we only need --depth=1. I imagine the following approach:

1. In dev-env-setup, clone Linux sources (w/ or w/o --depth=1).
2. In openpower-isa Makefile, invoke the script on the kernel sources.
Comment 30 Dmitry Selyutin 2023-09-17 19:43:17 BST
Yeah, since git (almost) never forgets, I've already dropped the generated file. The link's still actual anyway (I committed a revert), so you might take a look.

Andrey, what'd be the right way to split the activities so that I don't step on your toes? I assume the task consists of the following steps:

1. Update dev-env-setup and openpower-isa with the proper Linux kernel clone (easy to handle) and script invocation.
2. Extending openpower.syscalls module with the logic to lookup the PPC system call on the host.
3. Introducing a shim wrapper around syscall, which takes several integers and passes them SOMEHOW into the host registers. The only question I have there relates to resources.

Say we had invoked "sc" insn in ISACaller, and we have registers around. However, some of the registers are just pointers, some are descriptors. How'd I copy the memory from these simulated memory cells? As for descriptors, we obviously cannot pass them as is, and we'll kinda end up doing parts of OS job (e.g. introducing a map of sim:host descriptors and vice versa).

I assume this needs a trap mechanism by system call identifier in simulator. Am I right?
Comment 31 Luke Kenneth Casson Leighton 2023-09-17 20:09:55 BST
(In reply to Dmitry Selyutin from comment #30)
> Yeah, since git (almost) never forgets, I've already dropped the generated
> file. The link's still actual anyway (I committed a revert), so you might
> take a look.

i did. it's cool. would be nice to know what the function parameters are,
from somewhere. or at least the number of arguments, that's the most
critical information. is that known? i may have missed it

> Say we had invoked "sc" insn in ISACaller, and we have registers around.

sim.gpr (or, self.gpr)

> However, some of the registers are just pointers, some are descriptors.
> How'd I copy the memory from these simulated memory cells?

manually. see comment #26.  sim.mem (or, self.mem. look in mem.py)

> As for
> descriptors, we obviously cannot pass them as is, and we'll kinda end up
> doing parts of OS job (e.g. introducing a map of sim:host descriptors and
> vice versa).

siiiigh, yeeeees. i had a think and i don't believe the cavatools trick will
work in ISACaller: instead we will have to *literally* implement the syscalls
one by one.

as in: the implementation of write() would be done *by hand* by:

    fd = self.gpr(3)
    buf = self.gpr(4)
    count = self.gpr(5)
    actual_buf = bytes()
    for i in range(count):
       actual_bytes.append(self.mem.ld(buf+i, 1) # something like that
    self.gpr(3) = sys.write(fd, actual_bytes)

and errno somehow will need to get created/emulated/set, no idea how to do that.

> I assume this needs a trap mechanism by system call identifier in simulator.
> Am I right?

yeeeees - i did describe it somewhere, you need to "spot that a jump to address
0xC00 has been made". normally this would ACTUALLY contain (in a linux kernel)
an ACTUAL implementation (binary code) of an ACTUAL systemcall/OS implementation
however just like in riscv-spike and cavatools we are going to "hack it",
by enabling an option to ISACaller that just goes "if PC == xyz call this
special function instead of trying to execute instructions *AT* that address"

all quite dreadful but pretty standard - qemu, spike, cavatools - they all do it.
Comment 32 Dmitry Selyutin 2023-09-17 20:26:49 BST
(In reply to Luke Kenneth Casson Leighton from comment #31)
> (In reply to Dmitry Selyutin from comment #30)
> > Yeah, since git (almost) never forgets, I've already dropped the generated
> > file. The link's still actual anyway (I committed a revert), so you might
> > take a look.
> 
> i did. it's cool. would be nice to know what the function parameters are,
> from somewhere. or at least the number of arguments, that's the most
> critical information. is that known? i may have missed it

Yep, I implemented it. These are basically useless w/o information on arguments. Check Ctrl+F on this bug page for SYSARGS. :-)


> sim.gpr (or, self.gpr)
> sim.mem (or, self.mem. look in mem.py)
> as in: the implementation of write() would be done *by hand* by:
> 
>     fd = self.gpr(3)
>     buf = self.gpr(4)
>     count = self.gpr(5)
>     actual_buf = bytes()
>     for i in range(count):
>        actual_bytes.append(self.mem.ld(buf+i, 1) # something like that
>     self.gpr(3) = sys.write(fd, actual_bytes)

Aha, good enough to go. A temporary buffer for passing into the host syscall then. On a per-syscall basis, unfortunately.


> siiiigh, yeeeees. i had a think and i don't believe the cavatools trick will
> work in ISACaller: instead we will have to *literally* implement the syscalls
> one by one.
> 
> and errno somehow will need to get created/emulated/set, no idea how to do
> that.

Thanks God even as bad OS as Linux doesn't have this idiotic errno concept in kernel. They return a negative result to represent the error. That is, kernel returns -EINTR, and the userspace moves it to errno. "syscall" does the same stuff though, so we'll likely have to pick this from ctypes.get_errno().


> > I assume this needs a trap mechanism by system call identifier in simulator.
> > Am I right?
> 
> yeeeees - i did describe it somewhere, you need to "spot that a jump to
> address
> 0xC00 has been made". normally this would ACTUALLY contain (in a linux
> kernel)
> an ACTUAL implementation (binary code) of an ACTUAL systemcall/OS
> implementation
> however just like in riscv-spike and cavatools we are going to "hack it",
> by enabling an option to ISACaller that just goes "if PC == xyz call this
> special function instead of trying to execute instructions *AT* that address"
> 
> all quite dreadful but pretty standard - qemu, spike, cavatools - they all
> do it.

Here comes a microkernel in ISACaller, lol.


Hard to start, annoying to invent a reusable code, but still pretty doable and straightforward.
Comment 33 Dmitry Selyutin 2023-09-17 20:28:32 BST
(In reply to Dmitry Selyutin from comment #32)

> "syscall" does
> the same stuff though, so we'll likely have to pick this from
> ctypes.get_errno().

Just to clarify, I mean not an instruction but a libc wrapper (man 2 syscall, <unistd.h> and <sys/syscall.h>).
Comment 34 Luke Kenneth Casson Leighton 2023-09-17 21:30:46 BST
(In reply to Dmitry Selyutin from comment #32)
critical information. is that known? i may have missed it
> 
> Yep, I implemented it. 

i saw.  the commit is *tend* of thousands of lines long which is
precisely why the hard rule exists, as it is massively overloading
both my server and also my tablet.  it was 4 minutes to load the diff.

> These are basically useless w/o information on
> arguments. Check Ctrl+F on this bug page for SYSARGS. :-)

ok i see. ok that's auto-parseable. that's great, because autogenerating
the actual calls *even if "safed"* like in qemu-user, shouuuld be
reasonably straightforward.

i don't know how easy it would be to grab the size of data structs
for each object out from somewhere? even if it's done by hand
(or put into a lookup dictionary).

> 
> > sim.gpr (or, self.gpr)
> > sim.mem (or, self.mem. look in mem.py)
> > as in: the implementation of write() would be done *by hand* by:
> > 
> >     fd = self.gpr(3)
> >     buf = self.gpr(4)
> >     count = self.gpr(5)
> >     actual_buf = bytes()
> >     for i in range(count):
> >        actual_bytes.append(self.mem.ld(buf+i, 1) # something like that
> >     self.gpr(3) = sys.write(fd, actual_bytes)
> 
> Aha, good enough to go. A temporary buffer for passing into the host syscall
> then.

yes. sigh.

> On a per-syscall basis, unfortunately.

yes. sigh. but there *might* be enough information to actually
autogenerate (dynamic, runtime) everything.  

> 
> > siiiigh, yeeeees. i had a think and i don't believe the cavatools trick will
> > work in ISACaller: instead we will have to *literally* implement the syscalls
> > one by one.
> > 
> > and errno somehow will need to get created/emulated/set, no idea how to do
> > that.
> 
> Thanks God even as bad OS as Linux doesn't have this idiotic errno concept
> in kernel. They return a negative result to represent the error. That is,
> kernel returns -EINTR, and the userspace moves it to errno. "syscall" does
> the same stuff though, so we'll likely have to pick this from
> ctypes.get_errno().

i hesitate to actually allow the syscall itself, rather than an
"explicit emulated" one, but the issue of memory (see below) may
force our hand.



> Here comes a microkernel in ISACaller, lol.

userspace emulation of POSIX, in python... yes!


> 
> Hard to start, annoying to invent a reusable code, but still pretty doable
> and straightforward.

ohh fer goodness sake. i just realised, any memory allocated
(for the syscalls) you can't just discard it, you actually *need*
to keep it under a lookup table.

so when you get a shared memory lock you absolutely cannot just
blithely allocate a new area buffer.

ok this is complicated.

we *may* need to make a special version of sim.mem that *actually is
backed by a mmapped/malloced area of memory*, such that there is a
*DIRECT* one-to-one relationship between the addresses of the
emulator and when the syscalls take place.

this would have the advantage of not needing to map in/out in the
syscalls, you just literally pass the pointer-register to the syscall.

there is a way to call syscalls...

https://stackoverflow.com/questions/37032203/make-syscall-in-python

although this looks more complete/comprehensive:
https://github.com/ssavvides/execute-syscall

i *have* seen something that allows *direct* function calling... oh god
https://dev.to/adwaithrajesh/calling-asm-function-from-python-part-maybe-0-46e1
Comment 35 Dmitry Selyutin 2023-09-17 22:32:38 BST
(In reply to Luke Kenneth Casson Leighton from comment #34)
> (In reply to Dmitry Selyutin from comment #32)
> critical information. is that known? i may have missed it
> > 
> > Yep, I implemented it. 
> 
> i saw.  the commit is *tend* of thousands of lines long which is
> precisely why the hard rule exists, as it is massively overloading
> both my server and also my tablet.  it was 4 minutes to load the diff.

That's why I prefer $(git show), not URL's. :-) Anyway, that's rolled back.


> > These are basically useless w/o information on
> > arguments. Check Ctrl+F on this bug page for SYSARGS. :-)
> 
> ok i see. ok that's auto-parseable. that's great, because autogenerating
> the actual calls *even if "safed"* like in qemu-user, shouuuld be
> reasonably straightforward.
> 
> i don't know how easy it would be to grab the size of data structs
> for each object out from somewhere? even if it's done by hand
> (or put into a lookup dictionary).

Let's consider an example of just one system call. Even for `fstat`, there are 3 system calls with three different structures. That's only for i686; I'm not even speaking of compat syscalls. And I don't even mention stat, lstat, fstatat, fstatfs et al. They all have their multiple system calls. Recently they introduced statx, which should finally fix it (again).
Newer architectures have less of this nonsense, but still do. PPC has several fstat too: ppc32 supports at least 3 (just fstat), ppc64 has 2 (one of them is compat). There are other issues related to passing 64-bit integers too.
That's what happens when you attempt to guarantee userspace ABI but allow users to operate by other means than via libc wrappers.


> yes. sigh. but there *might* be enough information to actually
> autogenerate (dynamic, runtime) everything.

There is, but, unless you pass the same options used to build the kernel and likely build it indeed, it's damn complicated. At the very minimum you have to have the same uAPI files as the kernel generates based on tons of options. The best option is to take from other project; qemu user emulation should've done it.


> > Here comes a microkernel in ISACaller, lol.
> 
> userspace emulation of POSIX, in python... yes!

No, this is wrong. POSIX has no idea of system calls. That's not their level of abstraction. They operate in terms of API, and it just happens that many OSes choose to implement this API via syscalls. Quite an unfortunate tradition, frankly speaking; I'd prefer simpler building blocks. POSIX is powerful, but not a good candidate for kernel<->userspace cooperation. It serves a different purpose.


> > Hard to start, annoying to invent a reusable code, but still pretty doable
> > and straightforward.
> 
> ohh fer goodness sake. i just realised, any memory allocated
> (for the syscalls) you can't just discard it, you actually *need*
> to keep it under a lookup table.
> 
> so when you get a shared memory lock you absolutely cannot just
> blithely allocate a new area buffer.
> 
> ok this is complicated.
> 
> we *may* need to make a special version of sim.mem that *actually is
> backed by a mmapped/malloced area of memory*, such that there is a
> *DIRECT* one-to-one relationship between the addresses of the
> emulator and when the syscalls take place.
> this would have the advantage of not needing to map in/out in the
> syscalls, you just literally pass the pointer-register to the syscall.

It makes life easier, indeed. Still there will be mappings for... mmap itself. Basically to make these work you have to invent poor man's MM.


> there is a way to call syscalls...
> 
> https://stackoverflow.com/questions/37032203/make-syscall-in-python

I already told about it few comments ago. Yes, Linux libc wraps syscalls in syscall(2), converts codes to errno, and this is present in ctypes too (thus ctypes.get_errno() suggestion). On amd64 (and I think on most modern 64 archs) it's as tiny as just changing some of the registers due call/kernel-syscall conventions.


> i *have* seen something that allows *direct* function calling... oh god
> https://dev.to/adwaithrajesh/calling-asm-function-from-python-part-maybe-0-
> 46e1

No need and no point. In addition to complications of passing the parameters, you'll have to support different calling conventions. libc already takes care of that.


On the overall in separate comment.
Comment 36 Dmitry Selyutin 2023-09-17 22:47:56 BST
All in all, this task and its future depends on how far you want to go.

If you want a proper ABI emulation for another architecture -- you have to invent something like QEMU user mode. Or, better, just directly take it.

If we need some fixed number of system calls, or for some reasons want to pass these as is to host OS on our own without intermediate participants like qemu -- that's another story. But that another story has to have some bits depending on which system calls you need: either intermediate copies, or directly shared memory, plus parts of MM, plus parts of fd tree, etc. etc. Basically you'll end up inventing a toy OS inside the interpreter.

From comment 2 I assumed the second. That's an interesting thing to try checking out, though I must confess, in my opinion, the budget hardly covers even this experiment. The best I can suggest is preparing an infrastructure which makes this possible and demonstrating some really basic bits: say wrapping some exit(2) variant and maybe write(2) on STDOUT_FILENO and perhaps stuff like sleep and OS detection via say uname(2).
Comment 37 Luke Kenneth Casson Leighton 2023-09-17 22:57:23 BST
(In reply to Dmitry Selyutin from comment #35)
> (In reply to Luke Kenneth Casson Leighton from comment #34)
> > this would have the advantage of not needing to map in/out in the
> > syscalls, you just literally pass the pointer-register to the syscall.
> 
> It makes life easier, indeed. Still there will be mappings for... mmap
> itself. Basically to make these work you have to invent poor man's MM.

cavatools cheats, by overriding malloc realloc and free.
actually i believe it just makes free() a stub (saves complications)

if going down this route (a new sim.mem that *actually* reads/writes
to an actual area of malloc/mmao'd userspace memory) it will be
necessary to allocate it at a fixed address of a fixed size.

some hints lead to mmap with MMAP_FIXED and also mremap

https://stackoverflow.com/questions/19945350/allocate-a-memory-chunk-at-a-specified-address-in-linux-kernel

https://stackoverflow.com/questions/6446101/how-do-i-choose-a-fixed-address-for-mmap

the reason for picking a fixed address is so as to be able to compile
static binaries at a pre-arranged address.

i would greatly prefer exploring this route first and see how far it
gets rather than literally writing every syscall emulated in python.

> ctypes.get_errno() suggestion). On amd64 (and I think on most modern 64
> archs) it's as tiny as just changing some of the registers due
> call/kernel-syscall conventions.

i think we both understand what goes on, you happen to know more
details more readily, with more first-hand experience. always a good thing.
Comment 38 Luke Kenneth Casson Leighton 2023-09-17 23:06:29 BST
(In reply to Dmitry Selyutin from comment #36)
> All in all, this task and its future depends on how far you want to go.

enough to run "open and read and write some files" such as /dev/ttyUSB0
or other serial console.

and enough to say "success!" and justify another grant.

> depending on which system calls you need: either intermediate copies,
> or directly shared memory, plus parts of MM, plus parts of fd tree, etc.
> etc. Basically you'll end up inventing a toy OS inside the interpreter.

indeed.
 
> From comment 2 I assumed the second. That's an interesting thing to try
> checking out, though I must confess, in my opinion, the budget hardly covers
> even this experiment.

i know.

> The best I can suggest is preparing an infrastructure
> which makes this possible and demonstrating some really basic bits: say
> wrapping some exit(2) variant and maybe write(2) on STDOUT_FILENO and
> perhaps stuff like sleep and OS detection via say uname(2).

you can see why cavatools just literally farmed out verbatim guest to
host, no security whatsoever, and overrode malloc and free.

can we see how far the direct-syscall-with-new-mem.py gets?

if it really doesn't work out the fallback is an emulation in python,
with a few (very few) syscalls as a start.

in theeeoryyy we can borrow the cavatools budget allocated to the
same task. see bug #981

oh. https://bugs.libre-soc.org/show_bug.cgi?id=939#c1
Comment 39 Jacob Lifshay 2023-09-17 23:27:43 BST
(In reply to Luke Kenneth Casson Leighton from comment #37)
> if going down this route (a new sim.mem that *actually* reads/writes
> to an actual area of malloc/mmao'd userspace memory) it will be
> necessary to allocate it at a fixed address of a fixed size.

a fixed address is not necessary, all we need is to allocate a memory block and then add the base address of that block to all simulated memory operations. if we bind the allocated block to a python buffer object, python will do that for us, as well as bounds checking.

to implement emulated mmap, we can simply pick an unused address in that memory block and use MAP_FIXED on that calculated address.

this is exactly what wasm does (with some extra stuff for sandboxing, like fast bounds checking)
Comment 40 Jacob Lifshay 2023-09-18 03:53:24 BST
(In reply to Jacob Lifshay from comment #39)
> a fixed address is not necessary, all we need is to allocate a memory block
> and then add the base address of that block to all simulated memory
> operations. if we bind the allocated block to a python buffer object, python
> will do that for us, as well as bounds checking.

e.g.:
import mmap
mem = mmap.mmap(-1, 1 << 32, mmap.MAP_PRIVATE)  # create 4GiB block
print(mem[0x12345])  # read byte at 0x12345
mem[0x6789] = 0x12  # write byte at 0x6789

# emulate mmap helper code
import ctypes
libc = ctypes.CDLL("libc.so.6")
off_t = ctypes.c_long  # valid on ppc64le and x86_64 afaict
libc.mmap.argtypes = [
    ctypes.c_void_p, ctypes.c_size_t, ctypes.c_int,
    ctypes.c_int, ctypes.c_int, off_t]
libc.mmap.restype = ctypes.c_void_p
MAP_FIXED = 0x10

# emulate mmap
addr = pick_free_addr()
p = ctypes.c_char.from_buffer(mem, addr)
r = libc.mmap(p, MAP_FIXED, ...)
if r != p:
    return make_error_from_errno()
return addr
Comment 41 Luke Kenneth Casson Leighton 2023-09-18 08:19:30 BST
(In reply to Jacob Lifshay from comment #39)

> and then add the base address of that block to all simulated memory
> operations.

this is the bit that (a) requires identifying all memory buffers for
all syscalls (which is a stowstopping amount of work for the
available budget) and (b) does not work for code that relies on
address-offsets *in code*.

all *load store* operations executed would need offsetting... *if* they
were allocated by a syscall, but not otherwise? this is hopelessly
impractical to consider.

even (a) is too much work which is why cavatools directly maps
the guest program into host memoryspace (one-to-one and onto)
then overrides malloc and free.
Comment 42 Jacob Lifshay 2023-09-18 08:59:03 BST
(In reply to Luke Kenneth Casson Leighton from comment #41)
> (In reply to Jacob Lifshay from comment #39)
> 
> > and then add the base address of that block to all simulated memory
> > operations.
> 
> this is the bit that (a) requires identifying all memory buffers for
> all syscalls (which is a stowstopping amount of work for the
> available budget)

you're misunderstanding -- there's *one* block used for *all* simulated memory regardless of if we're running a syscall rn or not, read/write syscalls are passed a pointer pointing inside that block. 

> and (b) does not work for code that relies on
> address-offsets *in code*.

all *in-code* address offsets are already handled by python for the simulator (well, if we had used a bytesarray instead of a dict for simulated memory, since python adds the index to the bytesarray's base address).

the only time when manual offsetting is necessary is when python doesn't do it for you -- when manually calling raw c syscall wrapper functions.
> 
> all *load store* operations executed would need offsetting... *if* they
> were allocated by a syscall, but not otherwise?

no, they're always offset -- transparently, by python. you just access mem[123] and python accesses byte *(123 + mem.the_buffer_ptr), since that's how array indexing works.

> this is hopelessly
> impractical to consider.
> 
> even (a) is too much work which is why cavatools directly maps
> the guest program into host memoryspace (one-to-one and onto)
> then overrides malloc and free.

cavatools is written in C/C++ where direct memory read/wrires are just a pointer dereference away. ISACaller is written in python, where indexing into an bytesarray (or other buffer object, in our case, a mmap object) is the default way to access raw memory.
Comment 43 Jacob Lifshay 2023-09-18 09:03:38 BST
(In reply to Jacob Lifshay from comment #42)
> you're misunderstanding -- there's *one* block used for *all* simulated
> memory regardless of if we're running a syscall rn or not, read/write
> syscalls are passed a pointer pointing inside that block.

all the emulated mmap syscall will do is to go behind python's back and replace a piece of that *one* block with MAP_FIXED, python will still keep treating it as *one* block of memory.
Comment 44 Luke Kenneth Casson Leighton 2023-09-18 09:05:19 BST
(In reply to Jacob Lifshay from comment #42)

> all *in-code* address offsets are already handled by python for the
> simulator 

static binaries.  non-position-independent (non -fPIC) code.
think it through.
Comment 45 Jacob Lifshay 2023-09-18 09:48:32 BST
(In reply to Luke Kenneth Casson Leighton from comment #44)
> (In reply to Jacob Lifshay from comment #42)
> 
> > all *in-code* address offsets are already handled by python for the
> > simulator 
> 
> static binaries.  non-position-independent (non -fPIC) code.
> think it through.

all insns in those static binaries are simulated by the simulator.

so, when the simulator sees lbz r3, 28(r5), it effectively does
gprs[3] = mem[28 + gprs[5]]
mem.__getitem__ (python builtin) is what adds the offset.

so, if the statically linked binary's ELF headers says to load it with .data at 0x40000, then the binary runs an insn to store to .data + 0x10, the simulator will try to write to mem[0x40010], which python's __setitem__ will translate to
*(mem.the_base_addr + 0x40010) = the_byte
Comment 46 Dmitry Selyutin 2023-09-18 15:48:36 BST
I chose the cheapest generation approach. No fancy targets, just clone the kernel with --depth=1 upon dev-env-setup/hdl-dev-repos, then launch $(python3 -m openpower.syscalls ../linux) to generate the thing.

https://git.libre-soc.org/?p=dev-env-setup.git;a=commitdiff;h=cf35d78fff7db7baa4a69bfb50168e2778e7eb92
https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=180638ac02637f38301eb97d15a8590293b3a3a4
Comment 47 Luke Kenneth Casson Leighton 2023-09-18 16:22:30 BST
(In reply to Jacob Lifshay from comment #45)

> so, if the statically linked binary's ELF headers says to load it with .data
> at 0x40000, then the binary runs an insn to store to .data + 0x10, the
> simulator will try to write to mem[0x40010], which python's __setitem__ will
> translate to
> *(mem.the_base_addr + 0x40010) = the_byte

where is the money coming from to implement that?
Comment 48 Jacob Lifshay 2023-09-18 18:17:58 BST
(In reply to Luke Kenneth Casson Leighton from comment #47)
> (In reply to Jacob Lifshay from comment #45)
> 
> > so, if the statically linked binary's ELF headers says to load it with .data
> > at 0x40000, then the binary runs an insn to store to .data + 0x10, the
> > simulator will try to write to mem[0x40010], which python's __setitem__ will
> > translate to
> > *(mem.the_base_addr + 0x40010) = the_byte
> 
> where is the money coming from to implement that?

the task we'll make when we want to support emulating mmap and/or loading ELF binaries.

all we'd need is to change the Mem class to use that block from mmap.mmap instead of a dict, looking through it, i could do it in a few hours. probably less if nothing reaches into the Mem.mem dict and fiddles with it directly instead of calling the load/store functions.

https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/decoder/isa/mem.py;h=41d5b0b4df11592f609dfc07c9da57234e8b5626;hb=180638ac02637f38301eb97d15a8590293b3a3a4#l52
Comment 49 Andrey Miroshnikov 2023-09-18 18:38:04 BST
Sorry I haven't been responsive chaps in the last few days, I was too tired to work on this.

(In reply to Dmitry Selyutin from comment #30)
>
> Andrey, what'd be the right way to split the activities so that I don't step
> on your toes? I assume the task consists of the following steps:
> 
> 1. Update dev-env-setup and openpower-isa with the proper Linux kernel clone
> (easy to handle) and script invocation.
> 2. Extending openpower.syscalls module with the logic to lookup the PPC
> system call on the host.
> 3. Introducing a shim wrapper around syscall, which takes several integers
> and passes them SOMEHOW into the host registers. The only question I have
> there relates to resources.

I kind of get the gist of you're suggesting, although this is starting to go way beyond my understanding.

The bare minimum I was thinking about, was not even bother with syscalls, and just use bog standard python methods (like write()) to emulate syscall behaviour. With some syscalls (like exit(), we can't even use the linux syscall, because we just want to terminate the program running in ISACaller, not the python script itself).

How much actual kernel interaction do you need with ISACaller? Isn't printing to stdout already sufficient for a wide range of applications?


On another note, is there a way to reduce the ISACaller printing without SILENCE_LOG? SILENCE_LOG takes away most of it, but normal printing is way too much (don't understand much of it). To me ISACaller is still too much of a monster, and I'm not sure which files are better to approach (where are the GPR's/SPR's memory is, how to start/stop the simulator, etc.)
Comment 50 Dmitry Selyutin 2023-09-18 19:32:37 BST
(In reply to Andrey Miroshnikov from comment #49)
> Sorry I haven't been responsive chaps in the last few days, I was too tired
> to work on this.

Hi Andrey, no problems at all! I hope you got some rest.


> I kind of get the gist of you're suggesting, although this is starting to go
> way beyond my understanding.
> 
> The bare minimum I was thinking about, was not even bother with syscalls,
> and just use bog standard python methods (like write()) to emulate syscall
> behaviour. With some syscalls (like exit(), we can't even use the linux
> syscall, because we just want to terminate the program running in ISACaller,
> not the python script itself).

Part of the issue is that you still must detect what exact syscall is being passed (or, well, rather trapped by) ISACaller. So at the very minimum you need guest syscall table. Since we're going to route (at least some of) these to the host, we'll likely need host syscall table. We also need a mechanism to make both cooperate: shared memory, system call ids and arguments translation, fd tree, etc. etc. I've mostly just prepared a ground to dig. :-)


> How much actual kernel interaction do you need with ISACaller? Isn't
> printing to stdout already sufficient for a wide range of applications?

The answer really depends on the overall future of ISACaller and cavatools. If we go till the end of this road, this is basically the same as QEMU user mode (I know, I know, hardly comparable, but partially, in a spirit). For now, however, I want to have some mechanism which provides a basis for doing this.


> On another note, is there a way to reduce the ISACaller printing without
> SILENCE_LOG? SILENCE_LOG takes away most of it, but normal printing is way
> too much (don't understand much of it). To me ISACaller is still too much of
> a monster, and I'm not sure which files are better to approach (where are
> the GPR's/SPR's memory is, how to start/stop the simulator, etc.)

You should ask Luke. :-) I personally think that the idea to debug via print is good as long as this debug is not committed to the repository (in fact, I almost always debug by prints; but almost never commit this debug).
Comment 51 Andrey Miroshnikov 2023-09-18 20:03:33 BST
(In reply to Dmitry Selyutin from comment #50)
>
> Part of the issue is that you still must detect what exact syscall is being
> passed (or, well, rather trapped by) ISACaller. So at the very minimum you
> need guest syscall table. Since we're going to route (at least some of)
> these to the host, we'll likely need host syscall table.

You're right, thanks for doing that table btw.

> We also need a
> mechanism to make both cooperate: shared memory, system call ids and
> arguments translation, fd tree, etc. etc. I've mostly just prepared a ground
> to dig. :-)

Indeed, and again thanks for that. I'll just need to re-read those earlier comments by Luke and Jacob on memory, eventually will sink in :-)

> The answer really depends on the overall future of ISACaller and cavatools.
> If we go till the end of this road, this is basically the same as QEMU user
> mode (I know, I know, hardly comparable, but partially, in a spirit). For
> now, however, I want to have some mechanism which provides a basis for doing
> this.

I guess it's in our interest to (eventually) support a wide range of syscalls. When ISACaller is sufficiently optimised (into C) then running whole applications might actually become viable. And perhaps the efforts of that could work into cavatools.

> You should ask Luke. :-) I personally think that the idea to debug via print
> is good as long as this debug is not committed to the repository (in fact, I
> almost always debug by prints; but almost never commit this debug).

Yes, print statements have helped more times than I can count...
Comment 52 Dmitry Selyutin 2023-09-18 20:29:14 BST
Folks, I've played a bit more with these shiny system call tables, and added a simple class which can be used as a basis for ppc/ppc64/i386/amd64 conversion:

https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=b80670cfb193d148ff0419a14318e0f63900ef76

Usage example:

    from openpower.syscalls import Dispatcher

    dispatcher = Dispatcher(guest="ppc", host="amd64", logger=print)
    print(dispatcher(identifier=20))
    print(dispatcher(identifier=207))
    print(dispatcher.getpid())
    print(dispatcher.gettid())


This works as if somebody arrived to us with system calls 20 and 207 on PPC and attempted to wrap their execution to amd64 (which luckily is the platform I use). Basically it checks guest syscall table by identifier, finds the entry, then finds the backward mapping in host syscall table, then briefly inspects the arguments count (though we might even attempt to validate these). I also added a wrapper to call them by names, not just identifiers. The output is:

getpid 20 => 39
15293
getpid 20 => 39
15293
gettid 207 => 186
15293
gettid 207 => 186
1529

Note that these are equal due to obvious reasons (I'm too lazy to fork a thread).
Comment 53 Dmitry Selyutin 2023-09-18 20:30:00 BST
Basically, if we extend this class with memory mapping and fd mapping, this is what we want.
Comment 54 Andrey Miroshnikov 2023-09-18 20:34:34 BST
(In reply to Dmitry Selyutin from comment #52)
> Folks, I've played a bit more with these shiny system call tables, and added
> a simple class which can be used as a basis for ppc/ppc64/i386/amd64
> conversion:
> ... 
> This works as if somebody arrived to us with system calls 20 and 207 on PPC
> and attempted to wrap their execution to amd64 (which luckily is the
> platform I use). Basically it checks guest syscall table by identifier,
> finds the entry, then finds the backward mapping in host syscall table, then
> briefly inspects the arguments count (though we might even attempt to
> validate these). I also added a wrapper to call them by names, not just
> identifiers. The output is:
> 

This is brilliant! Thanks for doing this. During learning I was struggling how to use ctypes, this is so much more capable!

I'll give this a spin later.
Comment 55 Jacob Lifshay 2023-09-18 20:38:40 BST
(In reply to Dmitry Selyutin from comment #52)
> Folks, I've played a bit more with these shiny system call tables, and added
> a simple class which can be used as a basis for ppc/ppc64/i386/amd64
> conversion:

nice! though I wouldn't bother supporting i386...

note that some system calls pass in structs and stuff, and those structs often have different layouts between architectures, so they will need more complex translation than just moving registers around.
Comment 56 Dmitry Selyutin 2023-09-18 20:45:15 BST
(In reply to Andrey Miroshnikov from comment #54)
> (In reply to Dmitry Selyutin from comment #52)
> This is brilliant! Thanks for doing this. During learning I was struggling
> how to use ctypes, this is so much more capable!

Nah, ctypes are easy and sweet, compared to many CFFI (C foreign function interfaces) or other tools for C interop I saw. At least they are amazing for simple tasks, and here we mostly need to wrap only one function. I'd just extend them to deal with structures and unions in a dataclass-like format, though: the current syntax for this is annoying.

> I'll give this a spin later.

Sure, no rush!

I've updated the code calling convention a bit so that the first argument in __call__ is always expected to be a system call id (as it indeed happens IRL):

https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=ad27091ea159b284c1bda2b089f670b83e5681a7

(In reply to Jacob Lifshay from comment #55)
> (In reply to Dmitry Selyutin from comment #52)
> > Folks, I've played a bit more with these shiny system call tables, and added
> > a simple class which can be used as a basis for ppc/ppc64/i386/amd64
> > conversion:
> 
> nice! though I wouldn't bother supporting i386...

Naah it was so trivial I could not resist.

> note that some system calls pass in structs and stuff, and those structs
> often have different layouts between architectures, so they will need more
> complex translation than just moving registers around.

Yep, I know. That's why we have lookup the exact entry point and why there's a way to override some particular call by its name. :-) I'll extend this mechanism a bit though.
Comment 57 Dmitry Selyutin 2023-09-18 21:31:11 BST
I stepped back and revisited the whole calls hierarchy. From now on, to call by name, we use entry point, not just a syscall "name" (that is, dispatcher.sys_openat or dispatcher.compat_sys_openat, not just dispatcher.openat).

https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=5f9944b9de97ed790c34495b32d2cfbd91078a5b

The good news is, overriding a custom system call is easy:

class CustomDispatcher(syscalls.Dispatcher):
    def sys_exit(*arguments):
        raise 42 # not just an exit, but rather a portal!
Comment 58 Dmitry Selyutin 2023-09-18 21:37:33 BST
I suggest that at this point I reserve the rest of the works to Andrey. I think that, with a couple of minor modifications (e.g. extending it with memmap and fdtree arguments), this should be fine to wrap syscalls. Please try not to make it too invasive; the code should not itself depend on ISACaller, just on the interfaces.

Luke, what'd be your decision on the budget? I feel that I had to take some budget elsewhere, you suggested 981 IIRC. Would it be fine for me to flag 981 and reserve this task to you and Andrey? Is there something else I should do in scope of this task?
Comment 59 Andrey Miroshnikov 2023-09-18 21:44:48 BST
(In reply to Luke Kenneth Casson Leighton from comment #34)
> although this looks more complete/comprehensive:
> https://github.com/ssavvides/execute-syscall
> 

Before I forget, at least three syscalls (only 'exit' is really in scope of this task) need to be bypassed as they will affect the host python program: exit, pause, vfork:
https://github.com/ssavvides/execute-syscall/blob/master/execute_syscall.py#L210
Comment 60 Andrey Miroshnikov 2023-09-18 21:49:04 BST
(In reply to Dmitry Selyutin from comment #58)
> I suggest that at this point I reserve the rest of the works to Andrey. I
> think that, with a couple of minor modifications (e.g. extending it with
> memmap and fdtree arguments), this should be fine to wrap syscalls. Please
> try not to make it too invasive; the code should not itself depend on
> ISACaller, just on the interfaces.

Are you saying I should be able to do this without modifying ISACaller source at all?
I guess if there's a way to pause ISACaller execution, inspect mem/reg's, then actually I don't need to touch ISACaller at all!

> 
> Luke, what'd be your decision on the budget? I feel that I had to take some
> budget elsewhere, you suggested 981 IIRC. Would it be fine for me to flag
> 981 and reserve this task to you and Andrey? Is there something else I
> should do in scope of this task?

If there's not enough budget, I'm happy to split with Dmitry. Although your work on syscalls will eventually come in handy towards cavatools, so raising the budget is probably justified. Of course we'll wait on Luke's response.
Comment 61 Dmitry Selyutin 2023-09-18 22:34:43 BST
(In reply to Andrey Miroshnikov from comment #59)
> Before I forget, at least three syscalls (only 'exit' is really in scope of
> this task) need to be bypassed as they will affect the host python program:
> exit, pause, vfork:
> https://github.com/ssavvides/execute-syscall/blob/master/execute_syscall.
> py#L210

Almost everything is to be bypassed; other syscalls also make little sense unless they are bypassed. Some can be bypassed in a simpler way, e.g. those which don't have side-effects, like gettid, getpid, gettime, et al.; some need cooperation wrt resources (memory and descriptors) but are doable; some are difficult and I'm not even sure what their semantics would be (e.g. what does it mean to execve, fork or signal inside the emulator?).
The three to be bypassed are shown as those which make little sense in the context of the emulation; there is a rationale above the skip list. I wouldn't say exit makes no sense though, that's kinda like simulation stop in our realm. But you should discuss it with Luke.


(In reply to Andrey Miroshnikov from comment #60)
> (In reply to Dmitry Selyutin from comment #58)
> > I suggest that at this point I reserve the rest of the works to Andrey. I
> > think that, with a couple of minor modifications (e.g. extending it with
> > memmap and fdtree arguments), this should be fine to wrap syscalls. Please
> > try not to make it too invasive; the code should not itself depend on
> > ISACaller, just on the interfaces.
> 
> Are you saying I should be able to do this without modifying ISACaller
> source at all?
> I guess if there's a way to pause ISACaller execution, inspect mem/reg's,
> then actually I don't need to touch ISACaller at all!

Well, some bits are still to be touched. You have to establish the interrupt descriptor table. Basically, when you execute the system call, the processor triggers an interrupt; it happens that the processor is programmed or instructed by OS to jump at some special code section and continue execution there (with the return address and arguments saved, typically on stack or via registers). You can instruct the simulator to behave respectively when it sees this handler, i.e. when sumulator realizes it's on the same instruction counter as where the handler begins.
When you found the fact that you're executing the exact place as where the handler belongs, the Python code in simulator can simply be instructed to read self.gpr(XXX) based on the calling convention (just check ISA reference, they should mention "sc" parameters passing). Linux system calls generally don't use stack and never use FPRs, so you don't have to care about stack. Something like this (pseudocode, you have to dig it in ISACaller, I'm a rare guest there; I'm assuming registers 3..10, but you have to check):

$ cat sim.py
def __init__(self, initial_mem, regs):
    self.program_msrs_and_interrupts() # should likely be done by PPC assembly upon simulator start

def event_loop(self, ...):
    while True:
        syscall = syscalls.Dispatcher(guest="ppc", host=YOUR_HOST_AS_PER_PYTHON)
        pc = self.get_next_insn()
        if pc == MAGIC_HANDLER:
            sysnum = self.gpr(3)
            sysargs = [self.gpr(4), self.gpr(5), self.gpr(6), self.gpr(7), self.gpr(8), self.gpr(9), self.gpr(10)]
            rv = syscall(sysnum, *sysargs)
            self.gpr(3) = rv # beware, might be a multi-word; likely you need to set both


I'm not aware of PPC architecture enough; I could give you a vague hints on x86 only. I can try and check PPC ISA in this regard, if you want, but it'd be simpler to ask Jacob or Luke or perhaps Konstantinos (I'm not sure whether he dealt with PPC syscalls though). But I see that you alredy do something suspiciously similar in src/openpower/test/syscall/syscall_cases.py. :-)

Practically speaking, it's just the same function call, except that you do not jump directly. You interrupt the processor, it switches the context and priviledge level, then jumps to a specific pre-programmed location, then the kernel code serves the request. There's an awful lot of details inbetween these stages, but basically (dramatically simplified) this is it.
Comment 62 Dmitry Selyutin 2023-09-19 15:55:12 BST
Andrey, I think this is not the right budget distribution. :-) Remember, you still have to adjust the ISACaller, install the interrupts/traps/wowever-this-is-called-in-PPC. I'd rather prefer to take a lesser part for this, maybe 1000 or like this, and grab bug #981. Luke, could you, please, check, whether this is fine? I can create some code which converts the stuff to C so that it's better applicable to bug #981.
Comment 63 Dmitry Selyutin 2023-09-19 17:37:08 BST
Andrey, I've edited the budget again and increased yours and Luke's budget, picking only 1K here; I'm expecting that bug #981 can cover all the works I did. I'm thinking about C code generation for bug #981, though, to make it better candidate for cavatools incorporation. Stay tuned.
Comment 64 Luke Kenneth Casson Leighton 2023-09-19 18:36:11 BST
(In reply to Dmitry Selyutin from comment #62)
> Andrey, I think this is not the right budget distribution. :-)

i did tell andrey not to edit the budget assignments, but he had
already done it. i explained that you are a high-value contributor.
they will be restored so that you receive most, but also we may find
a way to increase. meeting tonight goes over it.
Comment 65 Luke Kenneth Casson Leighton 2023-09-19 18:41:22 BST
(In reply to Jacob Lifshay from comment #48)
> (In reply to Luke Kenneth Casson Leighton from comment #47)

> > where is the money coming from to implement that?
> 
> the task we'll make when we want to support emulating mmap and/or loading
> ELF binaries.

which has to be *right now* as there is only 4 months left before
the EU Assure Programme ENDS.

to be discussed tonight.

> all we'd need is to change the Mem class to use that block from mmap.mmap
> instead of a dict, looking through it, i could do it in a few hours.

yes it's real basic. unit test needed as well.

> probably less if nothing reaches into the Mem.mem dict and fiddles with it
> directly instead of calling the load/store functions.

mmmm... no. TestIssuer Test API has to bypass *nmigen* mem interface
but not the case with ISACaller as there is the MMU as well and messing
with the internals is Bad.

no need to support VM/MMU for this userspace-only mode.
Comment 66 Dmitry Selyutin 2023-09-21 00:00:20 BST
(In reply to Luke Kenneth Casson Leighton from comment #64)
> meeting tonight goes over it.

I'm kinda lost, to be honest. Andrey, do you have time to finish it, or you'll be completely buried under 6 feet of administrative joy? :-) I'm currently concentrated on bug #981, and I assumed that you'll have to handle #982. Please let me know if this is not the case. I don't think #981 will take too long to be finished.
Comment 67 Jacob Lifshay 2023-09-21 00:14:30 BST
(In reply to Dmitry Selyutin from comment #66)
> Practically speaking, it's just the same function call, except that you do
> not jump directly. You interrupt the processor, it switches the context and
> priviledge level, then jumps to a specific pre-programmed location, then the
> kernel code serves the request. There's an awful lot of details inbetween
> these stages, but basically (dramatically simplified) this is it.

well, imo it would be much easier to just add an `if` to ISACaller that checks if the current insn is `sc` (or, later, `scv`) and if it is, *skips* all privilege transitions and everything, replacing all actions of `sc` with just running the syscall translation code, and then advancing to the next instruction. I'd guess this is exactly what qemu-user does.

basically:

class ISACaller(...):
    ...
    def call(self, name):
        ...
        asmop = yield from self.get_assembly_name()
        log("call", ins_name, asmop)

        if not self.is_svp64_mode and asmop == "sc" and self.syscall_emulation:
            yield from self.emulate_syscall()
            self.update_pc_next()
            return
        ...
Comment 68 Jacob Lifshay 2023-09-21 00:27:52 BST
(In reply to Jacob Lifshay from comment #67)
> class ISACaller(...):
>     ...
>     def call(self, name):
>         ...
>         asmop = yield from self.get_assembly_name()
>         log("call", ins_name, asmop)
> 
>         if not self.is_svp64_mode and asmop == "sc" and self.syscall_emulation:
>             yield from self.emulate_syscall()
>             self.update_pc_next()
>             return
>         ...

    def emulate_syscall(self):
        syscall_num = self.gpr(0)
        if syscall_num in self.syscall_table:
            yield from self.syscall_table[syscall_num](self)
        else:
            self.cr.crl[0][CRFields.SO] = 1
            self.gpr[3] = ENOSYS
Comment 69 Andrey Miroshnikov 2023-09-22 10:58:33 BST
(In reply to Dmitry Selyutin from comment #66)
> (In reply to Luke Kenneth Casson Leighton from comment #64)
> > meeting tonight goes over it.
> 
> I'm kinda lost, to be honest. Andrey, do you have time to finish it, or
> you'll be completely buried under 6 feet of administrative joy? :-) I'm
> currently concentrated on bug #981, and I assumed that you'll have to handle
> #982. Please let me know if this is not the case. I don't think #981 will
> take too long to be finished.

Sorry for the late response Dmitriy.

If you think that you and Jacob can do a much quicker job at this, I'm happy to hand it over to you. Currently I have too much admin work to think about. Given that you seem to be in the zone atm, probably more efficient too.
Comment 70 Dmitry Selyutin 2023-09-22 12:06:24 BST
This is not difficult to handle at least to degree present in cavatools. However, I'd first like to know the fate of #981 which is already done.

https://bugs.libre-soc.org/show_bug.cgi?id=981#c13
https://bugs.libre-soc.org/show_bug.cgi?id=981#c14
Comment 71 Luke Kenneth Casson Leighton 2023-09-22 13:18:39 BST
(In reply to Jacob Lifshay from comment #67)

>         if not self.is_svp64_mode and asmop == "sc" and
> self.syscall_emulation:
>             yield from self.emulate_syscall()
>             self.update_pc_next()
>             return

this is the preferred method, where emulate_syscall() is
about... 10-15 lines of code covering *every* syscall,
because the mmap'd area is in the exact same memory location as
where the ELF relocation targetted it.

(plus mmap and malloc/free redirect/replacement)

(with an option to specify what that is, on the command-line)

(In reply to Jacob Lifshay from comment #68)

>     def emulate_syscall(self):
>         syscall_num = self.gpr(0)
>         if syscall_num in self.syscall_table:
>             yield from self.syscall_table[syscall_num](self)
>         else:
>             self.cr.crl[0][CRFields.SO] = 1
>             self.gpr[3] = ENOSYS

this is the "last resort" method that actually is in some
ways "better", because by literally implementing every single
POSIX (ok ok i know Dmitry, it's not actually POSIX) call
we have no "hacks" - just a hell of a lot of work ahead instead.
Comment 72 Luke Kenneth Casson Leighton 2023-09-22 13:28:45 BST
(In reply to Dmitry Selyutin from comment #66)

> I'm
> currently concentrated on bug #981, and I assumed that you'll have to handle
> #982. Please let me know if this is not the case. I don't think #981 will
> take too long to be finished.

ok so from a technical perspective, making any changes or improvements to
cavatools is a non-starter at the moment (far too much to do to get everything
else for cavatools-ppc64 going: decoder, compiler, everything).

cavatools-RISC-V works very well: it is high-performance and if there are
syscall mis-matches then that is solved by running *on native hardware*.
if any "redirection" tables are added it *actually defeats the objective*
of cavatools by slowing down its high performance (50x to 100x faster than
qemu).

for the exact same reason, *when* we come to doing cavatools-ppc64
(which is not right now, that was what the wednesday meeting was about)
then the exact same trick can be done: "if problems on syscall mis-match
due to host-guest being different, then run on an IBM POWER9".
Comment 73 Jacob Lifshay 2023-09-22 17:58:18 BST
(In reply to Luke Kenneth Casson Leighton from comment #71)
> (In reply to Jacob Lifshay from comment #68)
> 
> >     def emulate_syscall(self):
> >         syscall_num = self.gpr(0)
> >         if syscall_num in self.syscall_table:
> >             yield from self.syscall_table[syscall_num](self)
> >         else:
> >             self.cr.crl[0][CRFields.SO] = 1
> >             self.gpr[3] = ENOSYS
> 
> this is the "last resort" method that actually is in some
> ways "better", because by literally implementing every single
> POSIX (ok ok i know Dmitry, it's not actually POSIX) call
> we have no "hacks" - just a hell of a lot of work ahead instead.

the idea is self.syscall_table has every syscall we implement, not every syscall implemented by the linux kernel.
Comment 75 Dmitry Selyutin 2023-09-22 20:14:57 BST
We might opt to check more, say flags after sc instruction, but basically this is it. Note that I pass isacaller instance; we might find it handy for cases when we need to deal with the memory.
Comment 76 Jacob Lifshay 2023-09-22 20:18:36 BST
(In reply to Dmitry Selyutin from comment #74)
> If you could help me with what should be the action on exit/exit_group, I
> could demonstrate how we override the syscall. But, basically, it's this:
> 
> class SyscallEmulator(openpower.syscalls.Dispatcher):
>     def sys_exit(self, *_):
>         raise StopIteration
> 
>     def sys_exit_group(self, *_):
>         raise StopIteration

because most of ISACaller's methods are generators, StopIteration interferes with that, so imo we need a new exception class that the main loop catches and exits.
Comment 77 Dmitry Selyutin 2023-09-22 20:23:30 BST
(In reply to Jacob Lifshay from comment #76)
> because most of ISACaller's methods are generators, StopIteration interferes
> with that, so imo we need a new exception class that the main loop catches
> and exits.

Nah that was just a wild guess, I didn't really know what to do. But I saw that this is a generator, so I decided to raise it as an exit method. Appears that this guess was correct, just another exception should'be been used?
Comment 79 Luke Kenneth Casson Leighton 2023-09-22 21:08:07 BST
(In reply to Jacob Lifshay from comment #76)

> because most of ISACaller's methods are generators, StopIteration interferes
> with that, so imo we need a new exception class that the main loop catches
> and exits.

don't do massive indents of large swathes of code though. put the
try/except in one of the small functions... ah! execute_one. perfect.
it already is the main execution funtion and has a mem-exception catch.

don't put it anywhere else.
Comment 80 Luke Kenneth Casson Leighton 2023-09-22 21:13:19 BST
(In reply to Jacob Lifshay from comment #73)
> the idea is self.syscall_table has every syscall we implement, not every
> syscall implemented by the linux kernel.

this is the fallback position. it is a hell of a lot of work.
Comment 81 Jacob Lifshay 2023-09-22 21:15:31 BST
(In reply to Luke Kenneth Casson Leighton from comment #79)
> don't do massive indents of large swathes of code though. put the
> try/except in one of the small functions... ah! execute_one. perfect.
> it already is the main execution funtion and has a mem-exception catch.
> 
> don't put it anywhere else.

actually, imo it's better to put it here:
https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/decoder/isa/test_runner.py;h=b84354cc099cfba908629b9c17b903990fc79388;hb=c1af87691aaa83838514d3a5ed5ca85f14d86720#l79

just wrap the execute_one call in a try-except-break like is done for setup_one a few lines above
Comment 82 Jacob Lifshay 2023-09-22 21:19:58 BST
(In reply to Dmitry Selyutin from comment #74)
> ...I've been able to support system calls translation in ISACaller in scemu
> branch:

note that sc is kinda weird...on errors it sets CR0.SO and returns the error code in r3 as a *positive* integer.

scv is closer to linux's standard convention of small negative results means errors.
Comment 83 Luke Kenneth Casson Leighton 2023-09-22 21:20:26 BST
(In reply to Dmitry Selyutin from comment #74)
> With few fixes and updates...
> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=50160605d50567b43e6918f523646b5f37561814
> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=67eaadfa05989ea255159e5f00406ab6488806a3
> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=b2bbeec1bad4f579436f7edbb7e1a56dd5d875ff
> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=99c290ff878dbdb03ffd8b90964fcc1bd02452d0
> 
> ...I've been able to support system calls translation in ISACaller in scemu
> branch:

briiilliant, i love it.

*this* (the integration into ISACaller) is what i meant by "working *towards*
ISACaller" under bug #981. *this* is the work that justifies receiving
bug #981 budget.

this comment should have been posted under bug #981, with suitable
explanation that we are using bug #981 to *research working towards*
cavatools-ppc64, for a future grant.

see how that works?

leave it though, i will explain it to NLnet. or, explain it to Andrey and
he can (on preparing what to write) explain it to them.

welcome to the massive hidden burden of Administrative Project Management, 
Andrey.
Comment 84 Luke Kenneth Casson Leighton 2023-09-22 21:23:49 BST
(In reply to Jacob Lifshay from comment #81)
> just wrap the execute_one call in a try-except-break like is done for
> setup_one a few lines above

why do you think i said "do not do anything other than that function"?

because i know it is called directly by some of the Test API.

please listen, don't force me to explain things i do not want to spend time
explaining.

please permanently break this habit.

except when what i ask is clearly stupid :)
Comment 85 Luke Kenneth Casson Leighton 2023-09-22 21:25:46 BST
(In reply to Jacob Lifshay from comment #81)

> actually, imo it's better to put it here:
> https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/
> decoder/isa/test_runner.py;h=b84354cc099cfba908629b9c17b903990fc79388;
> hb=c1af87691aaa83838514d3a5ed5ca85f14d86720#l79

no because it's not the only place it's called.

keep it inside ISACaller please.
Comment 86 Jacob Lifshay 2023-09-22 21:29:43 BST
(In reply to Luke Kenneth Casson Leighton from comment #84)
> (In reply to Jacob Lifshay from comment #81)
> > just wrap the execute_one call in a try-except-break like is done for
> > setup_one a few lines above
> 
> why do you think i said "do not do anything other than that function"?

well, that doesn't work because it won't make the loop exit without signalling that it's done somehow...so, you can put the try-except in execute_one but it needs to return False or something that the caller can use so it knows to stop.

all callers need to be modified to detect that and stop looping (unless they don't call execute_one in a loop)
Comment 87 Luke Kenneth Casson Leighton 2023-09-22 22:46:46 BST
(In reply to Jacob Lifshay from comment #86)

> well, that doesn't work because it won't make the loop exit without
> signalling that it's done somehow...so, you can put the try-except in
> execute_one but it needs to return False or something that the caller can
> use so it knows to stop.

set a boolean flag instead. have setup_one throw KeyError.
document it and link here as part of the comments.

i don't want time wasted hunting down a change to the existing API.

> all callers need to be modified to detect that and stop looping (unless they
> don't call execute_one in a loop)

no. throw KeyError right at the start of setup_one. documented.

  65                     while index < len(instructions):
  66                         print("instr pc", pc)
  67                         try:
  68                             yield from simulator.setup_one()
  69                         except KeyError:  # instruction not in imem: stop
  70                             break
  71                         yield Settle()
Comment 88 Jacob Lifshay 2023-09-26 00:32:26 BST
I created a MemMMap class which can be used to get a raw
ctypes.c_ubyte * N array that can be passed to read/write/etc.

enabling it for ISACaller:
https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=9437aa56d550b9a66772068cf685b06e2d7d263f

testing reading/writing through the ctypes array returned by MemMMap.get_ctypes (method naming suggestions appreciated):

https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/decoder/isa/test_mem.py;h=e57d199148a86de07f67645bb009075005e9f2f3;hb=50cb080ba742df15e33422000b82a015c211aa5b#l97
Comment 89 Luke Kenneth Casson Leighton 2023-09-26 09:10:01 BST
(In reply to Jacob Lifshay from comment #88)
> I created a MemMMap class which can be used to get a raw
> ctypes.c_ubyte * N array that can be passed to read/write/etc.
> 
> enabling it for ISACaller:
> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=9437aa56d550b9a66772068cf685b06e2d7d263f

remember bug #1174 can you please put a # TODO on that
to explain, so it is not lost. i will crossref here

> testing reading/writing through the ctypes array returned by
> MemMMap.get_ctypes (method naming suggestions appreciated):

looks good

> https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/
> decoder/isa/test_mem.py;h=e57d199148a86de07f67645bb009075005e9f2f3;
> hb=50cb080ba742df15e33422000b82a015c211aa5b#l97

renember to add yourself 2023 to the copyright header.
Comment 90 Dmitry Selyutin 2023-10-17 19:07:24 BST
Folks, could you, please, take a look at scemu branch and summarize what's missing or needs to be improved before we can close this task? Just look at top 7 commits, ignore anything before.

https://git.libre-soc.org/?p=openpower-isa.git;a=shortlog;h=refs/heads/scemu
Comment 91 Dmitry Selyutin 2023-10-17 19:10:00 BST
Andrey, please discuss the budget with Luke and Jacob and sync it as you feel appropriate, OK? If there's something which can be allocated here based on amount of my works, that'd be great, but I feel that Jacob's works might end up unappreciated.
Comment 92 Jacob Lifshay 2023-10-17 19:24:53 BST
(In reply to Dmitry Selyutin from comment #91)
> Andrey, please discuss the budget with Luke and Jacob and sync it as you
> feel appropriate, OK? If there's something which can be allocated here based
> on amount of my works, that'd be great, but I feel that Jacob's works might
> end up unappreciated.

well, bug #1169 and bug #1173 are listed as blocking bug #983 since I think that's where they should get their funding from. if we decide that they shouldn't be under bug #983 because the ELF support should be in a new grant, then I think bug #1173 should probably get its funding from this bug.
Comment 93 Luke Kenneth Casson Leighton 2023-10-18 02:09:39 BST
(In reply to Dmitry Selyutin from comment #90)
> Folks, could you, please, take a look at scemu branch and summarize what's
> missing or needs to be improved before we can close this task? Just look at
> top 7 commits, ignore anything before.
> 
> https://git.libre-soc.org/?p=openpower-isa.git;a=shortlog;h=refs/heads/scemu

v quick. 2am.

 
+        if not self.is_svp64_mode and asmop in ("sc", "scv"):
+            identifier = self.gpr(0)

1. it is impossible to have svp64 on sc and scv. sv.sc or sv.scv will 
NEVER happen.

2. redirecting ALL sc and scv calls as i said on the call today
destroys unit tests on sc and scv (equivalent to qemu-system)

3. running in user mode *must* be made optional just as jacob
described in the chat logs of today's call (equivalent to qemu-user)
+            with Program(lst, bigendian=False) as program:
+                sim = self.run_tst_program(program, initial_regs,
                       >>>>usermode_emu_sc=True<<<<)

4. enabling usermode_emu_sc *must* enable the mmap memory mode as well.
Comment 94 Luke Kenneth Casson Leighton 2023-10-18 02:20:04 BST
(please ignore this for now, will edit and correct)

--- a/src/openpower/decoder/power_enums.py
+++ b/src/openpower/decoder/power_enums.py
@@ -811,6 +811,7 @@ _insns = [
+    "sc", "scv",

that's odd. i must have not added sc/scv unit tests
to ISACaller. these should be added (into trap_cases.py)
as it is important to verify the pseudocode when in
equivalent of qemu-system mode (the default only option
up until this bugreport)

https://libre-soc.org/openpower/isa/system/

hmmm actually only the sc one. scv i expect to fail
with an undefined variable "vectored" (sigh)

the unit test will be like this:

https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/test/trap/trap_cases.py;h=1501b8ab#l62

except there must be a stop/check when PC=0xC00.
Comment 95 Luke Kenneth Casson Leighton 2023-10-18 09:13:29 BST
https://git.libre-soc.org/?p=soc.git;a=blob;f=src/soc/fu/trap/main_stage.py;h=8127e226#l375

 364             with m.Case(MicrOp.OP_SC):
 374                 # jump to the trap address, return at cia+4
 375                 self.trap(m, 0xc00, cia_i+4)
 376                 self.msr_exception(m, 0xc00)

ok this is the HDL implementation of sc, which needs the unit test i
started attempting to describe in comment #94.

HDL testing through the TestAPI  *needs* ISACaller to compare against
and make sure that the MSR and PC are correct.

therefore we *cannot* have an unconditional redirection of sc instruction
(if asmop == "sc") because otherwise how can we test the HDL?

therefore... that flag (user_emu_syscall or whatever) is necessary
and ultimately must be propagated through to pypowersim command-line,
*exactly* as how you execute qemu-user vs qemu-system.
Comment 96 Dmitry Selyutin 2023-10-18 18:19:36 BST
I had to jiggle the commits somewhat due to addition of the arguments, and also I decided that it's better for syscall tests to be decoupled.

1. Redundant check for SVP64 is dropped:
https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=ba551ab85cb1dd7a0fd283b9fe3f70781429fc9c

2. use_syscall_emu parameter is now supported in test_runner, caller and runner modules:
https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=91d8332a0ea5fa54ebdfe070a4ef383f1189dc64
https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=1776e7690367a5f24f32722283a322560d345f55
https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=434cdd300e70fcb307f8d00b0553ec19ea67952a

3. Host-backed memory is now activated with some croaking around:
https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=c35dd70d41b1ccea51319071d80b18b723692f13

4. Tests are decoupled, the commit which poked test_caller.py is dropped:
https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=e69f8bfcc7c7c04459c408cdc5c06e3680ebc926

Is there anything else to be added considering the description and the title of the task?
Comment 97 Luke Kenneth Casson Leighton 2023-10-18 20:47:17 BST
(In reply to Dmitry Selyutin from comment #96)
> I had to jiggle the commits somewhat due to addition of the arguments, and
> also I decided that it's better for syscall tests to be decoupled.
> 
> 1. Redundant check for SVP64 is dropped:

great

> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=ba551ab85cb1dd7a0fd283b9fe3f70781429fc9c
> 
> 2. use_syscall_emu parameter is now supported in test_runner, caller and
> runner modules:

exxxcellent. the enabling mmap is good. otherwise it all goes horribly
awry...

> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=91d8332a0ea5fa54ebdfe070a4ef383f1189dc64
> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=1776e7690367a5f24f32722283a322560d345f55
> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=434cdd300e70fcb307f8d00b0553ec19ea67952a
> 
> 3. Host-backed memory is now activated with some croaking around:

yehh no surpriiise but a good way to do it

> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=c35dd70d41b1ccea51319071d80b18b723692f13
> 
> 4. Tests are decoupled, the commit which poked test_caller.py is dropped:

gooood.

> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=e69f8bfcc7c7c04459c408cdc5c06e3680ebc926
> 
> Is there anything else to be added considering the description and the title
> of the task?

ok there is a unit test needed in trap_cases.py (see comment #94)
which will demonstrate why the following is not correct to do:


1952         # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1953         # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1954         asmop = yield from self.get_assembly_name()
1955         log("call", ins_name, asmop,
1956             kind=LogKind.InstrInOuts)
1957 

      (put a comment here please, "in user mode emulate syscalls"
       or something)

1958         if asmop in ("sc", "scv"):
1959             if self.syscall is not None:
1960                 identifier = self.gpr(0)
1961                 arguments = map(self.gpr, range(3, 9))
1962                 result = self.syscall(identifier, *arguments)
1963                 self.gpr.write(3, result, False, self.namespace["XLEN"])
1964                 self.update_pc_next()
1965                 return
1966     >>>     else:   <<<<
1967     >>>>        self.call_trap(0x700, PIb.ILLEG) <<<<
1968     >>>         return <<<<

what lines 1966 to 1968 are doing is making "sc" *ILLEGAL* to
even execute.  

if scemu is not active (equivalent of qemu-user) you *MUST*
let sc's pseudocode be executed just like any other instruction:
https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=openpower/isa/system.mdwn;h=74f06c50#l13

   7 # System Call
   8 
   9 SC-Form
  10 
  11 * sc LEV
  12 
  13 Pseudo-code:
  14 
  15     SRR0 <-iea CIA + 4
  16     SRR1[33:36] <- 0
  17     SRR1[42:47] <- 0
  18     SRR1[0:32]  <- MSR[0:32]
  19     SRR1[37:41] <- MSR[37:41]
  20     SRR1[48:63] <- MSR[48:63]
  21     MSR <- new_value
  22     NIA <- 0x0000_0000_0000_0C00
  23 
  24 Special Registers Altered:
  25 
  26     SRR0 SRR1 MSR


so those three lines must go, as they prohibit us from running
the "sc" instruction when the simulator is in the same type
of mode as "qemu-system".

i will write an sc unit test and commit it so that you can run it,
and see what i mean ok?
Comment 98 Dmitry Selyutin 2023-10-18 21:01:57 BST
(In reply to Luke Kenneth Casson Leighton from comment #97)
> (In reply to Dmitry Selyutin from comment #96)
> what lines 1966 to 1968 are doing is making "sc" *ILLEGAL* to
> even execute.  

Ah OK, I begin to understand what you mean. The emulator just routes the execution to a well-known address, saving the registers and parts of context, right? And we basically emulate the whole world, kinda like regular qemu, and it'll be up to OS run in the emulator to establish the code at that address where we jump, is it what you mean?

> 
> so those three lines must go, as they prohibit us from running
> the "sc" instruction when the simulator is in the same type
> of mode as "qemu-system".

Not like that we were able to do it before. :-) I kinda had an impression from comment #2 that the point of this task was to enable userspace syscall emulation. OK, if we still have some work to do, it'd be great to adjust the budget: even the works I already completed were somewhat bigger to fit into 1000 I have as of now. :-)

> i will write an sc unit test and commit it so that you can run it,
> and see what i mean ok?

Sure, that'd be great! Thank you!
Comment 99 Dmitry Selyutin 2023-10-18 21:04:28 BST
(In reply to Luke Kenneth Casson Leighton from comment #97)
>       (put a comment here please, "in user mode emulate syscalls"
>        or something)

Sorry, I missed this part. I'll handle it when I'll deal with the emulator. Before that point, that was already obvious, based on `call_trap` in else branch and `if use_syscall_emu` in its counterpart. :-)
Comment 100 Luke Kenneth Casson Leighton 2023-10-18 22:19:52 BST
(In reply to Dmitry Selyutin from comment #98)

> Ah OK, I begin to understand what you mean. The emulator just routes the
> execution to a well-known address, saving the registers and parts of
> context, right?

saving registers no, swapping MSR->SRR1 and PC->SRR0, and then
setting up MSR to a "known good state suitable for a kernel"... yes.
i just sorted that out - it was a bit of a mess

> And we basically emulate the whole world, kinda like regular
> qemu,

aka qemu-system, yeeees

> and it'll be up to OS run in the emulator to establish the code at
> that address where we jump, is it what you mean?

by running the pseudocode for sc (after compiling to python) just like
any other pseudocode instruction... which i've just had to modify to
get the damn thing to work... yes.

https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=c91aa3ee

> > 
> > so those three lines must go, as they prohibit us from running
> > the "sc" instruction when the simulator is in the same type
> > of mode as "qemu-system".
> 
> Not like that we were able to do it before. :-)

in TestIssuer (the HDL) yes.  ISACaller no, because the Power ISA
spec says, in the pseudocode, "assign MSR to new_value"

   MSR <- new_value

then takes you on a stupid stupid wild goose chase "go to this page"
which then says "go to this other page"

> I kinda had an impression
> from comment #2 that the point of this task was to enable userspace syscall
> emulation.

yeees... but not in the process making it impossible to do the equivalent of
qemu-system! i was not expecting to have to sort out the sc pseudocode
"on-the-fly" but it was important to do so, so that when we come to
doing HDL-vs-ISACaller tests of "sc", ISACaller-in-qemusystem-mode
actually works.

gaah.

https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/test/trap/trap_cases.py;h=32b20125f#l54

you can see, after the sc instruction executes, what the expected
value of MSR, PC, SRR0 and SRR1 should be

  59   # expected results: PC should be at 0xc00 (sc address)
  60   e = ExpectedState(pc=0xc00)
  61   e.intregs[1] = 1
  62   e.sprs['SRR0'] = 4                  # PC to return to: CIA+4
  63   e.sprs['SRR1'] = 0x9000000000022903 # MSR to restore after sc return
  64   e.msr = 0x9000000000000001          # MSR changed to this by sc/trap

> OK, if we still have some work to do, it'd be great to adjust the
> budget: even the works I already completed were somewhat bigger to fit into
> 1000 I have as of now. :-)

yes i know. one for tomorrow.

> > i will write an sc unit test and commit it so that you can run it,
> > and see what i mean ok?
> 
> Sure, that'd be great! Thank you!

done, but i had to revert some code that jacob had added.
you'll need to re-run pywriter and pyfnwriter

jacob can you please take a look as i have absolutely no clue
why copy_assign_rhs was added, it really should not have been,
there are ways to write the pseudocode such that it is not
necessary to do (variable <- [0]*64 is the usual one)
Comment 101 Jacob Lifshay 2023-10-20 02:46:28 BST
(In reply to Jacob Lifshay from comment #92)
> (In reply to Dmitry Selyutin from comment #91)
> > Andrey, please discuss the budget <snip> I feel that Jacob's works might
> > end up unappreciated.
> 
> well, bug #1169 and bug #1173 are listed as blocking bug #983 since I think
> that's where they should get their funding from. <snip>

https://bugs.libre-soc.org/show_bug.cgi?id=1066#c5
Luke says I should get paid some for bug #1066, I think EUR 200-500 from this bug for my suggestions here and work on #1066 is a good amount based on how much time I spent. This is assuming bug #1069 and bug #1173 get paid from bug #983 instead of here.
Comment 102 Dmitry Selyutin 2023-10-20 18:31:19 BST
I've updated the code logic so that it executes in a common way, except that we can use emulation if this was desired:

https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=c215d24e6a3983e9da525ea04bc710abb605c256

I also checked that sc test from trap_cases works.
I tried to adopt the SRR1 and MSR checks there, but the values I got are different, no idea why. SRR0 check works though.

https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=a31c1b972039ff28c0d4e289e759c93e22bf65ff

Ideas on SRR1/MSR checks are highly appreciated.
Comment 103 Dmitry Selyutin 2023-10-20 18:34:31 BST
(In reply to Jacob Lifshay from comment #101)
> https://bugs.libre-soc.org/show_bug.cgi?id=1066#c5
> Luke says I should get paid some for bug #1066, I think EUR 200-500 from
> this bug for my suggestions here and work on #1066 is a good amount based on
> how much time I spent. This is assuming bug #1069 and bug #1173 get paid
> from bug #983 instead of here.

Sure. I'll let Andrey and Luke handle this.

(In reply to Luke Kenneth Casson Leighton from comment #100)
> (In reply to Dmitry Selyutin from comment #98)
> > OK, if we still have some work to do, it'd be great to adjust the
> > budget: even the works I already completed were somewhat bigger to fit into
> > 1000 I have as of now. :-)
> 
> yes i know. one for tomorrow.
Comment 104 Luke Kenneth Casson Leighton 2023-10-20 20:59:49 BST
(In reply to Dmitry Selyutin from comment #102)
> I've updated the code logic so that it executes in a common way, except that
> we can use emulation if this was desired:
> 
> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=c215d24e6a3983e9da525ea04bc710abb605c256

briilliant. so yes, if self.syscalls is not set up, that's perfect.

errr hang on though, you forgot these:

   -                self.update_pc_next()
   -                return

the actual sequence *to be emulated* is (i left out MSR):

   PC=0x00000 addi r0,r0,N # syscall number
   PC=0x00004 sc LEV=0     # syscall which causes saving to SRR1/SRR0
   PC=0x00C00 ....         # OS starts doing context-switch here
   PC=0x00C70 ....         # OS starts doing actual syscall about here
   PC=0x00Ce0 ....         # OS starts RESTORING context here
   PC=0x00Ce4 rfid         # rfid *RESTORES* SRR1/SRR0 into MSR/PC...
   PC=0x00008 usercode     # ... aaand we are back to after the syscall

therefore hmmm what must be done by the emulator is:

   PC=0x00000 addi r0,r0,N # syscall number
   PC=0x00004 sc LEV=0     # syscall *and effect of sc and rfid* EMULATED
   PC=0x00008 usercode     # ... aaand we are back to after the syscall

strictly speaking some bits of MSR must be set to zero,
it must be as if sc is called then rfid called.

> I also checked that sc test from trap_cases works.
> I tried to adopt the SRR1 and MSR checks there, but the values I got are
> different, no idea why.

ah. right. ok.  the clue is the modifications to SRR1 and MSR made
by the back-to-back sc and rfid.

BUT... to properly check this you have to have a program that
does both an sc and an rfid, hmmm....

but for now you are missing the "updatepcnext" and the return,
but this is still *not* quite correct, see below


> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=a31c1b972039ff28c0d4e289e759c93e22bf65ff
> 
> Ideas on SRR1/MSR checks are highly appreciated.

ok i know what to do.

1943     def call(self, name, CHEAT=False):

2056         # Usermode system call emulation
2057         if asmop in ("sc", "scv") and self.syscall is not None
                                       AND NOT CHEAT:
                 # must emulate the effect of sc followed by rfid.
                 self.call(asmop, CHEAT=True)
                 # now do the emulated syscall...
2058             identifier = self.gpr(0)
2059             arguments = map(self.gpr, range(3, 9))
2060             result = self.syscall(identifier, *arguments)
2061             self.gpr.write(3, result, False, self.namespace["XLEN"])
                 # now emulate "return from interrupt"
                 self.call("rfid")
                 # and we are done here. above, rfid updates pc already
                 return

see what's happening there? the sc is performed on a "cheat", which
*runs the sc pseudocode*, then you emulate the syscall, then
pretend that there was an OS that swapped all the context back and
as the last thing, does rfid which we can emulate by *running the
rfid pseudocode*

worst most elegant hack i can think of that gets the job done fast.
otherwise you have to analyse the effect of the sc and rfid pseudocode
back-to-back:

https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=openpower/isa/system.mdwn;h=958502d3#l48


to be absolutely honest there's no point when you can just do
self.call("sc") and self.call("rfid")


what i suggest is just to set MSR=0xfffffffffffffff and see what value
it gets set to afterwards.  then use that to work out the "masking"
effect.

test_syscall.py:

+        initial_sprs = {'SRR0': 0x12345678, 'SRR1': 0x5678}
+        sim = run_tst(prog, initial_regs,
+            initial_sprs=initial_sprs,
             initial_msr=0xffffffffffffffff,
+            use_syscall_emu=True)
Comment 105 Luke Kenneth Casson Leighton 2023-10-20 21:06:00 BST
i'm updating the budget to reflect quite a lot of related work
by jacob, and the shenanigens for me doing trap unt tests.
i have another one to write which is a bit sophisticated,
using the "offset" location to start at a non-standard
location (normally all programs start at 0x0000)
this will allow verifying what happens on a back-to-back sc+rfid
Comment 106 Dmitry Selyutin 2023-10-20 21:52:05 BST
(In reply to Luke Kenneth Casson Leighton from comment #104)
> (In reply to Dmitry Selyutin from comment #102)
> > I've updated the code logic so that it executes in a common way, except that
> > we can use emulation if this was desired:
> > 
> > https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> > h=c215d24e6a3983e9da525ea04bc710abb605c256
> 
> briilliant. so yes, if self.syscalls is not set up, that's perfect.
> 
> errr hang on though, you forgot these:
> 
>    -                self.update_pc_next()
>    -                return

https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/decoder/isa/test_syscall.py;h=74b336839ae677be9f25e66a8f3f422d7ef18718;hb=a31c1b972039ff28c0d4e289e759c93e22bf65ff#l19

This is explicitly checked here. The trick is that some code later already does it. Also, if we return, we won't execute the pseudocode, which is something we want to do.

> the actual sequence *to be emulated* is (i left out MSR):
> 
>    PC=0x00000 addi r0,r0,N # syscall number
>    PC=0x00004 sc LEV=0     # syscall which causes saving to SRR1/SRR0
>    PC=0x00C00 ....         # OS starts doing context-switch here
>    PC=0x00C70 ....         # OS starts doing actual syscall about here
>    PC=0x00Ce0 ....         # OS starts RESTORING context here
>    PC=0x00Ce4 rfid         # rfid *RESTORES* SRR1/SRR0 into MSR/PC...
>    PC=0x00008 usercode     # ... aaand we are back to after the syscall
> 
> therefore hmmm what must be done by the emulator is:
> 
>    PC=0x00000 addi r0,r0,N # syscall number
>    PC=0x00004 sc LEV=0     # syscall *and effect of sc and rfid* EMULATED
>    PC=0x00008 usercode     # ... aaand we are back to after the syscall

Is rfid handled by the kernel? Kinda like sysret/sysexit in x86?

> strictly speaking some bits of MSR must be set to zero,
> it must be as if sc is called then rfid called.
> 
> > I also checked that sc test from trap_cases works.
> > I tried to adopt the SRR1 and MSR checks there, but the values I got are
> > different, no idea why.
> 
> ah. right. ok.  the clue is the modifications to SRR1 and MSR made
> by the back-to-back sc and rfid.
> 
> BUT... to properly check this you have to have a program that
> does both an sc and an rfid, hmmm....

I don't quite get how trap_cases do it. They have separate tests for rfid, that's true. But I don't see rfid in the sc test case itself...

> but for now you are missing the "updatepcnext" and the return,

See above.

> but this is still *not* quite correct, see below
> 
> 
> > https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> > h=a31c1b972039ff28c0d4e289e759c93e22bf65ff
> > 
> > Ideas on SRR1/MSR checks are highly appreciated.
> 
> ok i know what to do.
> 
> 1943     def call(self, name, CHEAT=False):
> 
> 2056         # Usermode system call emulation
> 2057         if asmop in ("sc", "scv") and self.syscall is not None
>                                        AND NOT CHEAT:
>                  # must emulate the effect of sc followed by rfid.
>                  self.call(asmop, CHEAT=True)
>                  # now do the emulated syscall...
> 2058             identifier = self.gpr(0)
> 2059             arguments = map(self.gpr, range(3, 9))
> 2060             result = self.syscall(identifier, *arguments)
> 2061             self.gpr.write(3, result, False, self.namespace["XLEN"])
>                  # now emulate "return from interrupt"
>                  self.call("rfid")
>                  # and we are done here. above, rfid updates pc already
>                  return

This seems to update PC twice, if I'm not mistaken.

> to be absolutely honest there's no point when you can just do
> self.call("sc") and self.call("rfid")

Yes, mine impression is the same. After all, emulating system calls is not the only thing we have to support in order to emulate user mode; however, I feel that the rest is outside of the scope of the changes we initially discussed.

> what i suggest is just to set MSR=0xfffffffffffffff and see what value
> it gets set to afterwards.  then use that to work out the "masking"
> effect.
> 
> test_syscall.py:
> 
> +        initial_sprs = {'SRR0': 0x12345678, 'SRR1': 0x5678}
> +        sim = run_tst(prog, initial_regs,
> +            initial_sprs=initial_sprs,
>              initial_msr=0xffffffffffffffff,
> +            use_syscall_emu=True)

Sorry, I didn't get it. Do you suggest to check that MSR just got changed from that initial value (assertNotEqual)?
Comment 107 Dmitry Selyutin 2023-10-20 21:58:40 BST
(In reply to Dmitry Selyutin from comment #106)
> Is rfid handled by the kernel? Kinda like sysret/sysexit in x86?

Ah OK. I'm an idiot, that's just iret.
Comment 108 Dmitry Selyutin 2023-10-20 22:13:30 BST
Hm hm hm. Luke, if my statements on PC are correct, we might do something like this (also brutal but perhaps more obvious than CHEAT):


def do_outregs_nia(self, asmop, ins_name, info, outs,
                       ca_en, rc_en, ffirst_hit, ew_dst,
                       rfid=False):
    # snip
    if nia_update and not rfid:
        self.update_pc_next()


def call(self, name, rfid=False):
    # snip

    if asmop in ("sc", "scv") and self.syscall is not None:
        identifier = self.gpr(0)
        arguments = map(self.gpr, range(3, 9))
        result = self.syscall(identifier, *arguments)
        self.gpr.write(3, result, False, self.namespace["XLEN"])

    # snip

    # any modified return results?
    yield from self.do_outregs_nia(asmop, ins_name, info, outs,
                                    carry_en, rc_en, ffirst_hit, ew_dst,
                                    rfid=rfid)

    if asmop in ("sc", "scv") and self.syscall is not None:
        return self.call("rfid")


An alternative is:


def call(self, name):
    # snip
    scemu = (asmop in ("sc", "scv") and self.syscall is not None)
    yield from self.do_outregs_nia(asmop, ins_name, info, outs,
                                    carry_en, rc_en, ffirst_hit, ew_dst,
                                    update_pc=not scemu)

    if scemu:
        self.call("rfid", update_pc=False)
Comment 109 Dmitry Selyutin 2023-10-20 22:16:04 BST
Sorry, typo. Yes, I really like this:


def do_outregs_nia(self, asmop, ins_name, info, outs,
                       ca_en, rc_en, ffirst_hit, ew_dst,
                       update_pc=True):
    # snip
    if nia_update and update_pc:
        self.update_pc_next()


def call(self, name):
    # snip
    scemu = (asmop in ("sc", "scv") and self.syscall is not None)
    yield from self.do_outregs_nia(asmop, ins_name, info, outs,
                                    carry_en, rc_en, ffirst_hit, ew_dst,
                                    update_pc=not scemu)
    if scemu:
        self.call("rfid")
Comment 110 Luke Kenneth Casson Leighton 2023-10-20 22:27:14 BST
(In reply to Dmitry Selyutin from comment #106)
> (In reply to Luke Kenneth Casson Leighton from comment #104)
> > (In reply to Dmitry Selyutin from comment #102)
> > > I've updated the code logic so that it executes in a common way, except that
> > > we can use emulation if this was desired:
> > > 
> > > https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> > > h=c215d24e6a3983e9da525ea04bc710abb605c256
> > 
> > briilliant. so yes, if self.syscalls is not set up, that's perfect.
> > 
> > errr hang on though, you forgot these:
> > 
> >    -                self.update_pc_next()
> >    -                return
> 
> https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/
> decoder/isa/test_syscall.py;h=74b336839ae677be9f25e66a8f3f422d7ef18718;
> hb=a31c1b972039ff28c0d4e289e759c93e22bf65ff#l19
> 
> This is explicitly checked here. The trick is that some code later already
> does it. Also, if we return, we won't execute the pseudocode, which is
> something we want to do.
> 
> > the actual sequence *to be emulated* is (i left out MSR):
> > 
> >    PC=0x00000 addi r0,r0,N # syscall number
> >    PC=0x00004 sc LEV=0     # syscall which causes saving to SRR1/SRR0
> >    PC=0x00C00 ....         # OS starts doing context-switch here
> >    PC=0x00C70 ....         # OS starts doing actual syscall about here
> >    PC=0x00Ce0 ....         # OS starts RESTORING context here
> >    PC=0x00Ce4 rfid         # rfid *RESTORES* SRR1/SRR0 into MSR/PC...
> >    PC=0x00008 usercode     # ... aaand we are back to after the syscall

> Is rfid handled by the kernel? Kinda like sysret/sysexit in x86?

kernel - as in: the above sequence when PC is between 0xc00 and 0xce4... yes.

PC=0x000 USER
PC=0x004 USER
PC=0xc00 KERNEL
...
PC=0xce4 KERNEL
PC=0x008 USER

> I don't quite get how trap_cases do it. They have separate tests for rfid,
> that's true. But I don't see rfid in the sc test case itself...

that's because i have only just written it.
https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=9605c45
 
> > but for now you are missing the "updatepcnext" and the return,
> 
> See above.

you have misunderstood.
 
> This seems to update PC twice, if I'm not mistaken.

not "seems" - *DOES*. please use that sequence (also include the comments).
 
> > to be absolutely honest there's no point when you can just do
> > self.call("sc") and self.call("rfid")
> 
> Yes, mine impression is the same. After all, emulating system calls is not
> the only thing we have to support in order to emulate user mode; however, I
> feel that the rest is outside of the scope of the changes we initially
> discussed.

no it is not. the scope (goal) has not changed in any way. however i
had not predicted that the *implementation* would *require* the simulator
to not only run the full pseudocode of sc but also run the full pseudocode
of rfid *after* the emulated-syscall as a way to *meet* that goal.

> Sorry, I didn't get it. Do you suggest to check that MSR just got changed
> from that initial value (assertNotEqual)?

run the unit test that i have just written, you will then understand what
is required (which is written out in comment #114).
Comment 111 Dmitry Selyutin 2023-10-20 22:42:14 BST
(In reply to Luke Kenneth Casson Leighton from comment #110)
> > I don't quite get how trap_cases do it. They have separate tests for rfid,
> > that's true. But I don't see rfid in the sc test case itself...
> 
> that's because i have only just written it.
> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=9605c45

OK, will check.

>  
> > > but for now you are missing the "updatepcnext" and the return,
> > 
> > See above.
> 
> you have misunderstood.

Then, please, explain _what_ is misunderstood. If I do not return prematurely then I still get an incremented PC, which is shown by the test. I want the code to follow the same logic everywhere and avoid custom cases.

> > This seems to update PC twice, if I'm not mistaken.
> 
> not "seems" - *DOES*. please use that sequence (also include the comments).

I see one issue with the sequence you suggest. Even if we're fine with updating PC twice (and it seems we are, because we have to do rfid anyway), we have a completely custom sequence, and I don't see a good rationale to have it customized there.

> no it is not. the scope (goal) has not changed in any way. however i
> had not predicted that the *implementation* would *require* the simulator
> to not only run the full pseudocode of sc but also run the full pseudocode
> of rfid *after* the emulated-syscall as a way to *meet* that goal.

OK, this wording makes it clearer.

> > Sorry, I didn't get it. Do you suggest to check that MSR just got changed
> > from that initial value (assertNotEqual)?
> 
> run the unit test that i have just written, you will then understand what
> is required (which is written out in comment #114).

Ack.
Comment 112 Dmitry Selyutin 2023-10-20 22:46:49 BST
OK, considering that PC is incremented twice, why have CHEAT at all?


def call(self, name):
    # snip header

    scemu = (asmop in ("sc", "scv") and self.syscall is not None)
    if scemu:
        identifier = self.gpr(0)
        arguments = map(self.gpr, range(3, 9))
        result = self.syscall(identifier, *arguments)
        self.gpr.write(3, result, False, self.namespace["XLEN"])

    # snip middle

    # footer
    if scemu:
        self.call("rfid")
Comment 113 Luke Kenneth Casson Leighton 2023-10-21 19:07:27 BST
(In reply to Dmitry Selyutin from comment #112)
> OK, considering that PC is incremented twice, why have CHEAT at all?

because you have to run the emulated-sc *before* running
the emulated-syscall, and what if the syscall *needs the PC*?

reminder: speed is not important, at all.

>     # snip middle

... which is HUNDREDS of lines.

no.

the code is complex enough as it is. keep the group together.
Comment 114 Luke Kenneth Casson Leighton 2023-10-21 19:12:02 BST
https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=eee2cb24e2f

added in extra comments so it is clear the return result from the
syscall is in r3. also crossref'd to the discussion here
Comment 115 Dmitry Selyutin 2023-10-22 07:12:42 BST
(In reply to Luke Kenneth Casson Leighton from comment #113)
> ... which is HUNDREDS of lines.
> 
> no.
> 
> the code is complex enough as it is. keep the group together.

Perfect, this is a totally acceptable argument, exactly what I needed. You've convinced me.
Comment 116 Luke Kenneth Casson Leighton 2023-10-22 09:26:19 BST
(In reply to Dmitry Selyutin from comment #115)

> Perfect, this is a totally acceptable argument, exactly what I needed.
> You've convinced me.

it's... 3 years incremental addition, as a Finite State Machine.
adding Vertical-First and PACK/UNPACK (swapping of VL/SUBVL
loop ordering *on source and destination individually!!!*) simultaneously
introduced a special room in Hell, reserved just for me :)
Comment 117 Dmitry Selyutin 2023-10-22 14:19:16 BST
I still had to make it somewhat more complex, because self.call will not do anything, only `yield from self.call` will. Also, since basically our insn flow is unchanged, but we have to "inject" rfid instruction, I had to be somewhat creative.

https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=cea6b00e0cfb2acca2098794ad70c04d0d53cb29

I also had to introduce a way to pass initial_msr parameter into test_runner.

https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=e25fca65a5a0faecdd9040689b5fe1f44b9a64a7

One this is done, almost everything works, except MSR check:

https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=dfec8c6456adfd3690d5d8da5a78fe3aa6c96b66
Comment 118 Dmitry Selyutin 2023-10-22 14:38:30 BST
If I understand correctly, we must introduce some code residing at 0xc00, but I cannot think of a good way to handle it yet. We must either modify the Program so that every program has an additional code but this totally breaks the principle of least astonishment.

FTR, here's what I get for MSR mismatch:
  File "./src/openpower/decoder/isa/test_syscall.py", line 23, in run_tst_program
    self.assertEqual(sim.msr, 0xffffffffffffffff)         # MSR changed to this by sc/trap
SelectableInt(value=0xfbfffffefd7f10c5, bits=64) != 18446744073709551615
Comment 119 Luke Kenneth Casson Leighton 2023-10-22 15:37:28 BST
(edited to correct comment #90 to comment #97)

(In reply to Dmitry Selyutin from comment #117)
> I still had to make it somewhat more complex, because self.call will not do
> anything, only `yield from self.call` will. Also, since basically our insn
> flow is unchanged, but we have to "inject" rfid instruction, I had to be
> somewhat creative.
> 
> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=cea6b00e0cfb2acca2098794ad70c04d0d53cb29

ok you notice how in comment #97 i did *not* pass in the "cheat"
argument? that was deliberate. it means that the straight rfid
pseudocode gets called, as-is.

redirecting hrfid to rfid will break hrfid when it is implemented,
that should definitely not be done.


> I also had to introduce a way to pass initial_msr parameter into test_runner.

ah this is not a surprise

> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=e25fca65a5a0faecdd9040689b5fe1f44b9a64a7

pass in "None" instead and do "if initial_msr is None: initial_msr=0x9000000000001" (MSR.LE | MSR.SF)

> One this is done, almost everything works, except MSR check:
> 
> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=dfec8c6456adfd3690d5d8da5a78fe3aa6c96b66

aaawesome.

okaay so now that value 0xfffffeeeablahblah that can be the expected
e.msr!

and with the removal of the redirection of hrfid we are done!

(In reply to Dmitry Selyutin from comment #118)
> If I understand correctly, we must introduce some code residing at 0xc00,

noo: the call to self.syscall *is* the [kernel/OS] code at 0xc00!
(and yes that kernel/OS code as its last instruction includes an
rfid, hence why we have to explicitly call both sc and rfid)

> FTR, here's what I get for MSR mismatch:
>   File "./src/openpower/decoder/isa/test_syscall.py", line 23, in
> run_tst_program
>     self.assertEqual(sim.msr, 0xffffffffffffffff)         # MSR changed to
> this by sc/trap
> SelectableInt(value=0xfbfffffefd7f10c5, bits=64) != 18446744073709551615

great! see comment #97 again (2nd from last paragraph).
set e.msr = 0xfbfffffefd7f10c5 and we are pretty much done.
Comment 120 Dmitry Selyutin 2023-10-22 16:09:45 BST
(In reply to Luke Kenneth Casson Leighton from comment #119)
> ok you notice how in comment #90 i did *not* pass in the "cheat"
> argument? that was deliberate. it means that the straight rfid
> pseudocode gets called, as-is.

It still is, even with passing syscall_emu_active parameter. :-) I just needed something to check to make asmop be the same as ins_name; otherwise the code thinks we met an illegal instruction.

illegal = ins_name != asmop

> redirecting hrfid to rfid will break hrfid when it is implemented,
> that should definitely not be done.

IIRC I did it since both evaluate to OP_RFID. But yes, this should be dropped.

> > https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> > h=e25fca65a5a0faecdd9040689b5fe1f44b9a64a7
> 
> pass in "None" instead and do "if initial_msr is None:
> initial_msr=0x9000000000001" (MSR.LE | MSR.SF)

You mean ISACaller.__init__, right?

> > One this is done, almost everything works, except MSR check:
> > 
> > https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> > h=dfec8c6456adfd3690d5d8da5a78fe3aa6c96b66
> 
> aaawesome.
> 
> okaay so now that value 0xfffffeeeablahblah that can be the expected
> e.msr!

So you mean that we actually got the correct value, it's just that my expectations were incorrect?

> great! see comment #90 again (2nd from last paragraph).
> set e.msr = 0xfbfffffefd7f10c5 and we are pretty much done.

I'm confused. Comment #90 is my comment... :-) You probably meant something else?
Comment 121 Jacob Lifshay 2023-10-22 17:44:23 BST
(In reply to Luke Kenneth Casson Leighton from comment #119)
> (In reply to Dmitry Selyutin from comment #117)
> > https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> > h=e25fca65a5a0faecdd9040689b5fe1f44b9a64a7
> 
> pass in "None" instead and do "if initial_msr is None:
> initial_msr=0x9000000000001" (MSR.LE | MSR.SF)

please use DEFAULT_MSR instead, since it includes the bits needed for fp to work, or, if you need it to be in Problem state, please create a DEFAULT_USER_MSR that's just DEFAULT_MSR with PR set.
Comment 122 Luke Kenneth Casson Leighton 2023-10-22 19:56:24 BST
(In reply to Dmitry Selyutin from comment #120)
> (In reply to Luke Kenneth Casson Leighton from comment #119)
> > ok you notice how in comment #90 i did *not* pass in the "cheat"
> > argument? that was deliberate. it means that the straight rfid
> > pseudocode gets called, as-is.
> 
> It still is, even with passing syscall_emu_active parameter. :-) I just
> needed something to check to make asmop be the same as ins_name; otherwise
> the code thinks we met an illegal instruction.
> 
> illegal = ins_name != asmop

ah errr that shouldn't happen.  ohhh hang on yes i think i know what is
going on, the pc is pointing to 0xc00, of course there is no
instruction *at* 0xc00 so it gets a NULL op, which is "illegal",
and it all goes to shit from there.

so yes sigh "cheat" mode is necessary. sigh.  or we split out
ISACaller.call() into yet anoooother function. let me handle
that ok?


> IIRC I did it since both evaluate to OP_RFID.

OP_xxxx is only relevant for the HDL.  ISACaller uses the insndb
dictionary.  see all.py

the HDL does *further MANUAL explicit decoding* whenever an OP_xxxx
is shared like that.  OP_ADD is an extreme example, check the CSV
files, you will see there are something like *THIRTY* different
OP_ADD entries, all with completely different insndb parameters.


> > > https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> > > h=e25fca65a5a0faecdd9040689b5fe1f44b9a64a7
> > 
> > pass in "None" instead and do "if initial_msr is None:
> > initial_msr=0x9000000000001" (MSR.LE | MSR.SF)
> 
> You mean ISACaller.__init__, right?

*no*, under no circumstances change that. if you run all the
unit tests all hell will break loose.  when i said test_runner.py
(implicitly by replying to the commit-diff) i meant test_runner.py
and not anything else.


> So you mean that we actually got the correct value, it's just that my
> expectations were incorrect?

correct.

> > great! see comment #90 again (2nd from last paragraph).
> > set e.msr = 0xfbfffffefd7f10c5 and we are pretty much done.
> 
> I'm confused. Comment #90 is my comment... :-) You probably meant something
> else?

yes. comment #97. sorry. was on a train.

(In reply to Jacob Lifshay from comment #121)

> please use DEFAULT_MSR instead, since it includes the bits needed for fp to
> work, 

good call jacob. yes the whole default MSR thing really needs to
be a global setting at some point so that the entire test suite can
be run in BE mode. or 32-bit mode. but this is a frickin lot of work
and i still after 3 years cannot think of a good solution to that.

hmmm... now that i think about it, really jacob you should be using a
DEFAULT_MSR_FP to ensure that FP is *not* enabled by default *except*
for actual FP unit tests.

(i e. DEFAULT_MSR needs to be set to MSR.LE|MSR.SF)
Comment 123 Dmitry Selyutin 2023-10-22 20:41:15 BST
Folks, these MSR and SRR1 drive me nuts. Could you check, please, what goes wrong?


There are two commits:

https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=b3a3b220fc8815c8d679c7aec48e90002bcd587c

https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=6faf325b3f4368a5a93e6944590461c94f404251

Reproducer is:
SILENCELOG=true python3 ./src/openpower/decoder/isa/test_syscall.py | grep SYSCALL


You can see here the values I expected vs actual ones.

SYSCALL SRR1 0x9000000000002903 0x9000000000022903
SYSCALL  MSR 0x9000000000002903 0x9000000000000001

SRR1 gets its bit 17 set, but I'm struggling to find this bit anywhere. This is not present in DEFAULT_MSR, and, as it seems, is not even present as MSR field.

MSR gets several bits disabled. Bits 1, 8, 11 and 17 are not present as fields in MSRb. 


I tried following "4.3.1 System Linkage Instructions" and "7.5.14 System Call Interrupt" but apparently did something wrong. Any clue?
Comment 124 Jacob Lifshay 2023-10-22 20:54:16 BST
two things:
* rfid doesn't write all MSR bits
* function default arguments generally should not be mutable values, since if it's modified in the function, that modified value is used as the new default for all function calls

def run_tst_program(self, prog,
             initial_regs=[0] * 32):

idk if this will fix your bug, but it might help...
Comment 125 Dmitry Selyutin 2023-10-22 21:02:43 BST
(In reply to Luke Kenneth Casson Leighton from comment #122)
> (In reply to Dmitry Selyutin from comment #120)
> ah errr that shouldn't happen.  ohhh hang on yes i think i know what is
> going on, the pc is pointing to 0xc00, of course there is no
> instruction *at* 0xc00 so it gets a NULL op, which is "illegal",
> and it all goes to shit from there.

Nope, by that point it doesn't point to 0xc00. It still points to 0x0, sc. And then it compares sc vs rfid. So I have to replace the instruction temporarily.

> so yes sigh "cheat" mode is necessary. sigh.  or we split out
> ISACaller.call() into yet anoooother function. let me handle
> that ok?

Sure, np. I couldn't come up with a better way to handle it other than temporarily overriding instruction.

> > > > https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> > > > h=e25fca65a5a0faecdd9040689b5fe1f44b9a64a7
> > > 
> > > pass in "None" instead and do "if initial_msr is None:
> > > initial_msr=0x9000000000001" (MSR.LE | MSR.SF)
> > 
> > You mean ISACaller.__init__, right?
> 
> *no*, under no circumstances change that. if you run all the
> unit tests all hell will break loose.  when i said test_runner.py
> (implicitly by replying to the commit-diff) i meant test_runner.py
> and not anything else.

Yeah already done.

> > So you mean that we actually got the correct value, it's just that my
> > expectations were incorrect?
> 
> correct.

I still have different expectations. :-) See comment #123.
Comment 126 Dmitry Selyutin 2023-10-22 21:04:58 BST
(In reply to Jacob Lifshay from comment #124)
> two things:
> * rfid doesn't write all MSR bits
> * function default arguments generally should not be mutable values, since
> if it's modified in the function, that modified value is used as the new
> default for all function calls
> 
> def run_tst_program(self, prog,
>              initial_regs=[0] * 32):
> 
> idk if this will fix your bug, but it might help...

Likely the first one should be the reason. As for the second one, this should be fixed as well, though my troubles start even on the first test.
Comment 127 Dmitry Selyutin 2023-10-22 21:20:58 BST
Nope, it doesn't help, even if I literally copy&paste sc and rfid generated code.
I'm looking at ISACaller.TRAP code and find this comment somewhat suspicios:

        # set exception bits.  TODO: this should, based on the address
        # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
        # bits appropriately.  however it turns out that *for now* in all
        # cases (all trap_addrs) the exact same thing is needed.
        self.msr[MSRb.IR] = 0
        self.msr[MSRb.DR] = 0
        self.msr[MSRb.FE0] = 0
        self.msr[MSRb.FE1] = 0
        self.msr[MSRb.EE] = 0
        self.msr[MSRb.RI] = 0
        self.msr[MSRb.SF] = 1
        self.msr[MSRb.TM] = 0
        self.msr[MSRb.VEC] = 0
        self.msr[MSRb.VSX] = 0
        self.msr[MSRb.PR] = 0
        self.msr[MSRb.FP] = 0
        self.msr[MSRb.PMM] = 0
        self.msr[MSRb.TEs] = 0
        self.msr[MSRb.TEe] = 0
        self.msr[MSRb.UND] = 0
        self.msr[MSRb.LE] = 1
Comment 128 Dmitry Selyutin 2023-10-22 21:46:07 BST
(In reply to Dmitry Selyutin from comment #123)
> SRR1 gets its bit 17 set, but I'm struggling to find this bit anywhere.

Seems it's caused by this line:

self.spr['SRR1'][trap_bit] = 1  # change *copy* of MSR in SRR1
trap_bit is PIb.TRAP, which is 46, which is (64 - 17 - 1).
Comment 129 Dmitry Selyutin 2023-10-22 22:03:30 BST
OK, enabling this bit fixes the SRR1:

        SRR1[PIb.TRAP] = 1

https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=75887d596e2d067931382d20b2885d93be86c878

Still no glue about MSR, it has several bits inactive after the code gets executed.
Comment 130 Luke Kenneth Casson Leighton 2023-10-22 22:17:12 BST
(In reply to Dmitry Selyutin from comment #129)
> OK, enabling this bit fixes the SRR1:
> 
>         SRR1[PIb.TRAP] = 1

hmmm that should *not* be necessary. it is handled by self.TRAP(0xc00)
which is in the system.mdwn pseudocode for sc.

> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=75887d596e2d067931382d20b2885d93be86c878
> 
> Still no glue about MSR, it has several bits inactive after the code gets
> executed.

yes. that is correct behaviour.

i will have a look at this tomorrow ok?
Comment 131 Jacob Lifshay 2023-10-22 22:20:18 BST
(In reply to Luke Kenneth Casson Leighton from comment #130)
> (In reply to Dmitry Selyutin from comment #129)
> > OK, enabling this bit fixes the SRR1:
> > 
> >         SRR1[PIb.TRAP] = 1
> 
> hmmm that should *not* be necessary. it is handled by self.TRAP(0xc00)
> which is in the system.mdwn pseudocode for sc.

i think you misunderstood, luke. dmitry added that to his test case, which tries to reproduce the SRR1 to see if the simulator is correct. he didn't change that part of the simulator
Comment 132 Luke Kenneth Casson Leighton 2023-10-22 23:03:25 BST
(In reply to Jacob Lifshay from comment #131)

> i think you misunderstood, luke. dmitry added that to his test case, which
> tries to reproduce the SRR1 to see if the simulator is correct. 

ahh ok.

> he didn't change that part of the simulator

rright, i missed that (not able to look closely, just got back from
travelling today).

yes... it's complicated. sorting this for the HDL (copying microwatt
rather than Power ISA spec) LITERALLY tool over 2 years to EVENTUALLY
get right.

only by running microwatt's binary unit tests *and the linux kernel*
under verilator which took at least two months doing nothing else
was i able to finally get MSR interrupt and sc/rfid compatibility
with microwatt.
Comment 133 Luke Kenneth Casson Leighton 2023-10-22 23:37:38 BST
dmitry just so you know (i will look at this tomorrow):

  11 * sc LEV
  12 
  13 Pseudo-code:
  14 
  15     SRR0 <-iea CIA + 4
  16     SRR1[33:36] <- 0
  17     SRR1[42:47] <- 0
  18     SRR1[0:32]  <- MSR[0:32]
  19     SRR1[37:41] <- MSR[37:41]
  20     SRR1[48:63] <- MSR[48:63]
  21     TRAP(0xC00)  <<<<--- this ACTUALLY calls ISACaller.TRAP(0xc00)

which you will find at... errr.... here:

1318     def TRAP(self, trap_addr=0x700, trap_bit=PIb.TRAP):
1319         """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
1320 ...
     ...
     ....
1339         self.spr['SRR1'][trap_bit] = 1  # change *copy* of MSR in SRR1

so yes, this is why you should find that SRR1[PIb.TRAP] has been set to 1
because that's what ISACaller.TRAP() does. whether that is the right
thing to do, if you *really* want to look at Power ISA spec around page
1070 the interrupt tables and behaviours please feel free but no bonus
points given for doing so :)
Comment 134 Dmitry Selyutin 2023-10-23 07:03:23 BST
(In reply to Luke Kenneth Casson Leighton from comment #133)
> dmitry just so you know (i will look at this tomorrow):
> 
>   11 * sc LEV
>   12 
>   13 Pseudo-code:
>   14 
>   15     SRR0 <-iea CIA + 4
>   16     SRR1[33:36] <- 0
>   17     SRR1[42:47] <- 0
>   18     SRR1[0:32]  <- MSR[0:32]
>   19     SRR1[37:41] <- MSR[37:41]
>   20     SRR1[48:63] <- MSR[48:63]
>   21     TRAP(0xC00)  <<<<--- this ACTUALLY calls ISACaller.TRAP(0xc00)
> 
> which you will find at... errr.... here:
> 
> 1318     def TRAP(self, trap_addr=0x700, trap_bit=PIb.TRAP):
> 1319         """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
> 1320 ...
>      ...
>      ....
> 1339         self.spr['SRR1'][trap_bit] = 1  # change *copy* of MSR in SRR1
> 
> so yes, this is why you should find that SRR1[PIb.TRAP] has been set to 1
> because that's what ISACaller.TRAP() does.

Luke, I obviously found it (comment #128). I'd have expected this to be cleared after return from interrupt, though; but that's just a logical expectation.

> but no bonus
> points given for doing so :)

I wrote the syscall generator, all the logic for emulation, several tests and spent an awful lot of time debugging all parts of this. And for all this I got 1800 EUR. Thank you, I know there're no bonus points, there's no need to state the obvious.

I'm hardcodimg the expected MSR in test. Not a single damn minute on this task anymore.
Comment 135 Jacob Lifshay 2023-10-23 07:12:27 BST
(In reply to Luke Kenneth Casson Leighton from comment #105)
> i'm updating the budget to reflect quite a lot of related work
> by jacob, and the shenanigens for me doing trap unt tests.

I'm expecting to get paid for bug #1173 as part of bug #983. So, assuming that isn't part of this bug's budget, I don't think I did EUR 1000 worth of work, so can you give EUR 500 of it to Dmitry, leaving EUR 500 for me?
Comment 136 Dmitry Selyutin 2023-10-23 07:14:02 BST
No Jacob, I object. You earned these. So did everybody. My point is that the whole task was underestimated considering the efforts.
Comment 137 Dmitry Selyutin 2023-10-23 07:19:04 BST
(In reply to Dmitry Selyutin from comment #134)
> I'm hardcodimg the expected MSR in test. Not a single damn minute on this
> task anymore.

https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=2d0ad46d3d674b8ab03da7ff325de04ce555c619

I'll wait for CI to be completed and then will merge the whole branch into master.
Comment 138 Jacob Lifshay 2023-10-23 07:25:00 BST
(In reply to Dmitry Selyutin from comment #137)
> (In reply to Dmitry Selyutin from comment #134)
> > I'm hardcodimg the expected MSR in test. Not a single damn minute on this
> > task anymore.
> 
> https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;
> h=2d0ad46d3d674b8ab03da7ff325de04ce555c619
> 
> I'll wait for CI to be completed and then will merge the whole branch into
> master.

CI will not automatically start since git mirroring is currently disabled, and Luke has not given me permission to have it automatically run on any shorter period than 24hr:
https://bugs.libre-soc.org/show_bug.cgi?id=1162

That said, I will manually push your commits to the mirrors so CI can run this time
Comment 139 Jacob Lifshay 2023-10-23 07:27:26 BST
(In reply to Jacob Lifshay from comment #138)
> That said, I will manually push your commits to the mirrors so CI can run
> this time

https://salsa.debian.org/Kazan-team/mirrors/openpower-isa/-/jobs/4841167
Comment 140 Dmitry Selyutin 2023-10-23 07:31:37 BST
Thank you Jacob! Do we have current master results nearby? I'd like to skip tests which already fail (if any).
Comment 141 Jacob Lifshay 2023-10-23 07:32:50 BST
(In reply to Dmitry Selyutin from comment #140)
> Thank you Jacob! Do we have current master results nearby? I'd like to skip
> tests which already fail (if any).

https://salsa.debian.org/Kazan-team/mirrors/openpower-isa/-/jobs/4841214
Comment 142 Jacob Lifshay 2023-10-23 08:10:40 BST
(In reply to Dmitry Selyutin from comment #140)
> Thank you Jacob! Do we have current master results nearby? I'd like to skip
> tests which already fail (if any).

because programmerjake/readd-rhs-copy (bug #1066) hasn't been merged yet, a lot of tests fail, enough that CI isn't useful since it stops at 10 failures.

Testing on my computer:

master branch at eee2cb24e2f1185b2a47cb56e94c94d3d51efcdb:
> FAILED src/openpower/decoder/isa/test_caller_fmv_fcvt.py::TestFMvFCvt5::test
> FAILED src/openpower/decoder/isa/test_caller_fmv_fcvt.py::TestFMvFCvt1::test
> FAILED src/openpower/decoder/isa/test_caller_fmv_fcvt.py::TestFMvFCvt6::test
> FAILED src/openpower/decoder/isa/test_caller_fmv_fcvt.py::TestFMvFCvt2::test
> FAILED src/openpower/decoder/isa/test_caller_fmv_fcvt.py::TestFMvFCvt3::test
> FAILED src/openpower/decoder/isa/test_caller_fmv_fcvt.py::TestFMvFCvt4::test
> FAILED src/openpower/decoder/isa/test_caller_svp64_fptrans.py::TestSVP64FPTrans::test
> FAILED src/openpower/decoder/isa/test_caller_fptrans.py::TestFPTrans::test - ...
> FAILED src/openpower/decoder/isa/test_caller_fminmax.py::TestFMinMax::test - ...
> FAILED src/openpower/decoder/isa/test_caller_fmv_fcvt.py::TestFMvFCvt0::test
> FAILED src/openpower/decoder/isa/test_caller_fmv_fcvt.py::TestSVP64FMvFCvtCases::test
> FAILED src/openpower/decoder/isa/test_caller_bitmanip_av.py::TestAV::test - A...
> FAILED src/openpower/decoder/isa/test_caller_syscall.py::TestSysCall::test - ...
> FAILED src/openpower/decoder/isa/test_caller_trap.py::TrapTest::test - Assert...
> FAILED src/openpower/sv/trans/test_pysvp64dis.py::SVSTATETestCase::test_20_cmp
> FAILED src/openpower/sv/trans/test_pysvp64dis.py::SVSTATETestCase::test_36_extras_rldimi
> FAILED src/openpower/sv/trans/test_pysvp64dis.py::SVSTATETestCase::test_36_extras_rldimi_
> FAILED src/openpower/sv/trans/test_pysvp64dis.py::SVSTATETestCase::test_37_extras_rldimi
> = 18 failed, 440 passed, 75 skipped, 19 xfailed, 819 warnings in 411.65s (0:06:51) =

scemu branch at 2d0ad46d3d674b8ab03da7ff325de04ce555c619:
> FAILED src/openpower/decoder/isa/test_caller_bcd_full.py::BCDFullTestCase::test_cbcdtd_3
> FAILED src/openpower/decoder/isa/test_caller_bcd_full.py::BCDFullTestCase::test_cbcdtd_7
> FAILED src/openpower/decoder/isa/test_caller_bcd_full.py::BCDFullTestCase::test_addg6s_7
> FAILED src/openpower/decoder/isa/test_caller.py::DecoderTestCase::test_branch_ctr
> FAILED src/openpower/decoder/isa/test_caller.py::DecoderTestCase::test_cmp - ...
> FAILED src/openpower/decoder/isa/test_caller.py::DecoderTestCase::test_rlwimi
> FAILED src/openpower/decoder/isa/test_caller.py::DecoderTestCase::test_mtcrf
> FAILED src/openpower/decoder/isa/test_caller_fp.py::DecoderTestCase::test_fpload
> FAILED src/openpower/decoder/isa/test_caller_bcd_full.py::BCDFullTestCase::test_cdtbcd_3
> FAILED src/openpower/decoder/isa/test_caller_bcd_full.py::BCDFullTestCase::test_addg6s_3
> FAILED src/openpower/decoder/isa/test_caller.py::DecoderTestCase::test_addi
> <snip>
> = 216 failed, 245 passed, 75 skipped, 19 xfailed, 4857 warnings in 370.82s (0:06:10) =
Comment 143 Jacob Lifshay 2023-10-23 08:18:38 BST
my guess of the issue is:
if initial_msr is None and use_syscall_emu:
    initial_msr = DEFAULT_MSR

initial_msr needs to be changed to not be None even when use_syscall_emu isn't set, since None isn't a valid value.
Comment 144 Dmitry Selyutin 2023-10-23 08:29:24 BST
OK, initial_msr of None got passed to ISACaller from test_runner. I updated it so that it's changed from None to DEFAULT_MSR. However, ISACaller has initial_msr as 0, so more problems can be expected. I'll not make it DEFAULT_MSR, and instead will pass DEFAULT_MSR from the test; test_runner will by default use 0, as ISACaller does.

I've quickly rebased and squashed the commits. Jacob, could you, please, relauch it?
Comment 145 Dmitry Selyutin 2023-10-23 08:30:30 BST
(In reply to Jacob Lifshay from comment #143)
> my guess of the issue is:
> if initial_msr is None and use_syscall_emu:
>     initial_msr = DEFAULT_MSR
> 
> initial_msr needs to be changed to not be None even when use_syscall_emu
> isn't set, since None isn't a valid value.

Yep, exactly. However, I changed it, now I pass DEFAULT_MSR from the test and use 0 by default (exactly as ISACaller has).
Comment 146 Luke Kenneth Casson Leighton 2023-10-23 08:51:27 BST
(In reply to Jacob Lifshay from comment #142)

> because programmerjake/readd-rhs-copy (bug #1066) hasn't been merged yet, 

do it if they pass on the branch.

(In reply to Dmitry Selyutin from comment #145)

> Yep, exactly. However, I changed it, now I pass DEFAULT_MSR from the test
> and use 0 by default (exactly as ISACaller has).

gooood. this is the best approach. changing default behaviour for
thousands of unit tests is ennnnntiiirely inappropriate without
a full review!!!
Comment 147 Luke Kenneth Casson Leighton 2023-10-23 09:07:57 BST
(In reply to Dmitry Selyutin from comment #134)

> Luke, I obviously found it (comment #128). 

i am tracking this remotely, from memory of working with the code
over *two years* ago, without being able to run it. please be
patient, it is not obvious to me asi cannot remember.

> I'd have expected this to be cleared after return from interrupt,
> though; but that's just a logical expectation.

no, that is "rfid"'s job to clear it because that is the "return
from interrupt" instruction. (or, more to the point, to copy
the bit from SRR1 as you could have nested interrupts)

if the test had also run rfid not just "sc 0" then yes you would
expect to see it cleared.

but because the test only runs "sc 0" the test is *still inside the
kernel/OS* (emulated)
Comment 148 Jacob Lifshay 2023-10-23 09:09:05 BST
(In reply to Dmitry Selyutin from comment #144)
> OK, initial_msr of None got passed to ISACaller from test_runner. I updated
> it so that it's changed from None to DEFAULT_MSR. However, ISACaller has
> initial_msr as 0, so more problems can be expected. I'll not make it
> DEFAULT_MSR, and instead will pass DEFAULT_MSR from the test; test_runner
> will by default use 0, as ISACaller does.
> 
> I've quickly rebased and squashed the commits. Jacob, could you, please,
> relauch it?

I ran all the tests, only to realize I didn't generate the syscalls json, so I figured out how to run the script for generating json (that needs to be part of the Makefile, though imo you don't have to do it as part of this bug) and tried it on /usr/src/linux-headers-5.15.0-... which didn't work, so I git cloned Linux 6.5.8 and regenerated the json and reran the tests:

> = 18 failed, 443 passed, 75 skipped, 19 xfailed, 822 warnings in 400.52s (0:06:40) =

exactly the same tests as master, so, unless you wanted to fix the below test first, feel free to merge:
src/openpower/decoder/isa/test_caller_syscall.py::TestSysCall::test

I'm going to sleep very soon, so you'll have to run tests yourself or ask someone else if you need more testing.
Comment 149 Jacob Lifshay 2023-10-23 09:10:13 BST
I will mention that I noticed there's a rfscv instruction that looks like it pairs with scv instead of rfid.
Comment 150 Luke Kenneth Casson Leighton 2023-10-23 15:11:48 BST
(In reply to Jacob Lifshay from comment #149)
> I will mention that I noticed there's a rfscv

out of scope.

i would have defined the task as "implement syscalls
including vectored ones"
Comment 151 Dmitry Selyutin 2023-10-23 18:16:54 BST
(In reply to Jacob Lifshay from comment #148)
> exactly the same tests as master, so, unless you wanted to fix the below
> test first, feel free to merge:
> src/openpower/decoder/isa/test_caller_syscall.py::TestSysCall::test

Not at all. First, it checks mostly the same as other tests (registers, MSR, PC). Second, if we need to check memory interaction, these changes are for you in scope of another task. :-) I rebased atop of scemu branch and pushed to master based on the fact that everything works.
Comment 152 Dmitry Selyutin 2023-10-23 18:17:42 BST
(In reply to Jacob Lifshay from comment #148)
> (In reply to Dmitry Selyutin from comment #144)
> I ran all the tests, only to realize I didn't generate the syscalls json

https://git.libre-soc.org/?p=dev-env-setup.git;a=blob;f=hdl-dev-repos;h=14a13c8b4874fd4a8512de24baf0b0792d39f054;hb=HEAD#l83
Comment 153 Dmitry Selyutin 2023-10-23 18:18:53 BST
Anything else needed here, or I can write a summary?
Comment 154 Luke Kenneth Casson Leighton 2023-10-23 18:56:51 BST
(In reply to Dmitry Selyutin from comment #153)
> Anything else needed here,

let us check it works (and do a final review)

> or I can write a summary?

reminder again what michiel wrote: there is no need to write summaries.
writing summaries wastes your time because everyone here knows what
was done.

i.e.: if you want to spend the time writing a summary feel free but
you will not get more money for doing so!

(In reply to Jacob Lifshay from comment #135)

> I'm expecting to get paid for bug #1173 as part of bug #983. So, assuming
> that isn't part of this bug's budget, I don't think I did EUR 1000 worth of
> work, so can you give EUR 500 of it to Dmitry, leaving EUR 500 for me?

no jacob because as Project Lead i am authorizing payment from THIS
budget for work done on OTHER (related *and unrelated*) bugs

we have done this many times in 5 years.

as long as we work together on many tasks even unrelated ones NLnet
is quite flexible about who gets paid and for what.

i am however going to give dmitry more money from *my* budget, and also
from andrey's (because he is subcontracted by RED)

reminder dmitry that you only need express the value of what you are
doing.  we can always find another bugreport to allocate additional
funds, or reduce the scope down to "working *TOWARDS* the original
Milestone".

NLnet does *not* expect any of us to go into debt to complete pure Research.
Comment 155 Dmitry Selyutin 2023-10-23 19:08:55 BST
(In reply to Luke Kenneth Casson Leighton from comment #154)
> (In reply to Dmitry Selyutin from comment #153)
> > Anything else needed here,
> 
> let us check it works (and do a final review)

Sure.

> > or I can write a summary?
> 
> reminder again what michiel wrote: there is no need to write summaries.
> writing summaries wastes your time because everyone here knows what
> was done.

I actually assumed from bug #981 that we need to write this kind of documentation as the ultimate comment.

> i.e.: if you want to spend the time writing a summary

Not at all.

> (In reply to Jacob Lifshay from comment #135)
> 
> > I'm expecting to get paid for bug #1173 as part of bug #983. So, assuming
> > that isn't part of this bug's budget, I don't think I did EUR 1000 worth of
> > work, so can you give EUR 500 of it to Dmitry, leaving EUR 500 for me?
> 
> no jacob because as Project Lead i am authorizing payment from THIS
> budget for work done on OTHER (related *and unrelated*) bugs
> 
> we have done this many times in 5 years.
> 
> as long as we work together on many tasks even unrelated ones NLnet
> is quite flexible about who gets paid and for what.
> 
> i am however going to give dmitry more money from *my* budget, and also
> from andrey's (because he is subcontracted by RED)
> 
> reminder dmitry that you only need express the value of what you are
> doing.  we can always find another bugreport to allocate additional
> funds, or reduce the scope down to "working *TOWARDS* the original
> Milestone".
> 
> NLnet does *not* expect any of us to go into debt to complete pure Research.

Well, as I mentioned, my comments are related to the fact that this exact task ended up being underrated. I'd say all of us earned it well, it's just that cumulative we should've earned more. But OK, up to you.
Comment 156 Jacob Lifshay 2023-10-23 19:14:06 BST
(In reply to Dmitry Selyutin from comment #155)
> I actually assumed from bug #981 that we need to write this kind of
> documentation as the ultimate comment.

iirc that's only needed if we think the auditor could be suspicious about the amount paid for the apparent amount of work done.
Comment 157 Luke Kenneth Casson Leighton 2023-10-23 20:41:11 BST
dmitry i'm running on an armv8l host (kindle tablet, due to circumstances)
the default is hardcoded to amd64 in openpower.syscalls?
Comment 158 Jacob Lifshay 2023-10-23 20:56:48 BST
(In reply to Luke Kenneth Casson Leighton from comment #157)
> dmitry i'm running on an armv8l host (kindle tablet, due to circumstances)
> the default is hardcoded to amd64 in openpower.syscalls?

afaict it's not, it falls back to uname.machine, but probably needs a new entry to convert armv8l to aarch64 (on my phone uname.machine is aarch64):
https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/decoder/isa/caller.py;hb=6d56fed8edcd256b9264bac81cf897a596b58e53#l1140

actually, it just has no entries for aarch64:
https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/syscalls/__init__.py;h=5b349ea9e00e646419a3e80e0867bc55967e17f5;hb=6d56fed8edcd256b9264bac81cf897a596b58e53#l117
 117             "i386": i386,
 118             "amd64": amd64,
 119             "ppc": ppc,
 120             "ppc64": ppc64,
 121             "riscv32": riscv32,
 122             "riscv64": riscv64,
Comment 159 Dmitry Selyutin 2023-10-23 21:18:54 BST
Ah yes, sorry, I only used it with amd64 and ppc. Let me handle that.
Comment 160 Jacob Lifshay 2023-10-23 21:21:33 BST
(In reply to Luke Kenneth Casson Leighton from comment #157)
> dmitry i'm running on an armv8l host (kindle tablet, due to circumstances)
> the default is hardcoded to amd64 in openpower.syscalls?

luke, can you run `uname -m` and tell us if it says aarch64 or something else?
Comment 162 Dmitry Selyutin 2023-10-23 21:36:44 BST
(In reply to Dmitry Selyutin from comment #161)
> I'll check dev scripts.

Ah right, we generate JSON for all architectures I found as syscall.tbl, it's just that not all of these architectures are supported in Dispatcher. Luke, could you try now, please? Things should work; if not -- follow the commits from comment #161 and also post the uname().machine in Python.
Comment 163 Dmitry Selyutin 2023-10-23 22:14:04 BST
(In reply to Jacob Lifshay from comment #156)
> (In reply to Dmitry Selyutin from comment #155)
> > I actually assumed from bug #981 that we need to write this kind of
> > documentation as the ultimate comment.
> 
> iirc that's only needed if we think the auditor could be suspicious about
> the amount paid for the apparent amount of work done.

That's damn unfortunate they aren't as suspicious in an opposite scenario... :-)
Comment 164 Luke Kenneth Casson Leighton 2023-10-23 23:33:51 BST
(In reply to Dmitry Selyutin from comment #155)

> I actually assumed from bug #981 that we need to write this kind of
> documentation as the ultimate comment.

no, you missed that it was an anomaly, that i am required as Project
Team Lead and Signatory to the Memorandum of Understanding to check
anything that i think potentially could be red-flagged by an Auditor.

when i have a satisfactory answer, it goes in the bugreport, and we
move on. done.

(NLnet has raised queries and requested additional comments approximately
*eight* times in 5 years. they read every single bugreport as part of
Due-Diligence, and sometimes it is just not clear. i do not tell people
about this, because they email me directly as Project Team Lead)

> > i.e.: if you want to spend the time writing a summary
> 
> Not at all.

good! :)

> task ended up being underrated. I'd say all of us earned it well, it's just
> that cumulative we should've earned more.

under other bugreports. already taken care of. you very much need to
stop thinking in terms of "the task is the task: do it exactly...
or else". it is far more flexible than that, being fundamentaly based
on trust.


(In reply to Jacob Lifshay from comment #156)

> iirc that's only needed if we think the auditor could be suspicious about
> the amount paid for the apparent amount of work done.

correction: if *I as Project Team Lead and Signatory to the MOU*,
or NLnet themselves (eight times in 5 years) do not have an answer
ready *if* the Auditor is suspicious.  hence why NLnet read literally
every bugreport.

you are not the Signatory to the MoU jacob so you do not have the
direct responsibility, although it is all our responsibility.
Comment 165 Luke Kenneth Casson Leighton 2023-10-23 23:35:00 BST
+from . import ARCH
 from . import Dispatcher
 from . import UnknownSyscall

oh, sorry Dmitry: the Project Coding Standards prohibit relative
imports.  please convert these to full-path imports.
Comment 166 Luke Kenneth Casson Leighton 2023-10-23 23:55:43 BST
jacob see #1066 reduce the mem block down to 1<<29 please

dmitry the return result is "-1" but is coming out at 0xffffffffff...

this is *possibly* due to using termux (proot). which would be a pisser.

i will have to fire up the laptop tomorrow (amd64).


ERROR: test_sc_dup (__main__.SyscallTestCase)                                  ----------------------------------------------------------------------         Traceback (most recent call last):                                               File "/home/libresoc/src/openpower-isa/src/openpower/decoder/isa/test_syscall.py", line 107, in test_sc_dup                                                     st1 = os.fstat(fd1)                                                        OverflowError: Python int too large to convert to C int                                                                                                       ======================================================================         FAIL: test_sc_getpid (__main__.SyscallTestCase)                                ----------------------------------------------------------------------         Traceback (most recent call last):                                               File "/home/libresoc/src/openpower-isa/src/openpower/decoder/isa/test_syscall.py", line 82, in test_sc_getpid                                                   self.assertEqual(sim.gpr(3), os.getpid())                                  AssertionError: SelectableInt(value=0xffffffffffffffff, bits=64) != 26211                                                                                     ======================================================================         FAIL: test_sc_getuid (__main__.SyscallTestCase)                                ----------------------------------------------------------------------         Traceback (most recent call last):                                               File "/home/libresoc/src/openpower-isa/src/openpower/decoder/isa/test_syscall.py", line 90, in test_sc_getuid                                                   self.assertEqual(sim.gpr(3), os.getuid())                                  AssertionError: SelectableInt(value=0xffffffffffffffff, bits=64) != 1000                                                                                      ----------------------------------------------------------------------         Ran 3 tests in 41.027s
Comment 167 Jacob Lifshay 2023-10-24 01:12:29 BST
(In reply to Luke Kenneth Casson Leighton from comment #166)
> jacob see #1066 reduce the mem block down to 1<<29 please

I'm assuming you meant bug #1173.
> 
> dmitry the return result is "-1" but is coming out at 0xffffffffff...

I would guess the issue is that uname is being used, but what you actually need is the arch of the user-space executable, not the kernel, since Luke seems to have a armhf user-space and aarch64 kernel. after some experimentation, it looks like you can use:
python3 -c 'import sysconfig; print(sysconfig.get_config_var("HOST_GNU_TYPE"))'

for armhf:
armv8l-unknown-linux-gnueabihf
for arm64:
aarch64-unknown-linux-gnu
for i386:
i686-pc-linux-gnu
for x86_64:
x86_64-pc-linux-gnu
for ppc64el:
powerpc64le-unknown-linux-gnu
Comment 168 Jacob Lifshay 2023-10-24 01:42:02 BST
(In reply to Jacob Lifshay from comment #167)
> for armhf:
> armv8l-unknown-linux-gnueabihf
> for arm64:
> aarch64-unknown-linux-gnu
> for i386:
> i686-pc-linux-gnu
> for x86_64:
> x86_64-pc-linux-gnu
> for ppc64el:
> powerpc64le-unknown-linux-gnu

for riscv64:
riscv64-unknown-linux-gnu
Comment 169 Jacob Lifshay 2023-10-24 01:51:02 BST
(In reply to Jacob Lifshay from comment #168)
> (In reply to Jacob Lifshay from comment #167)
> > for armhf:
> > armv8l-unknown-linux-gnueabihf

this is the value I get for armhf on multiarch with an emulated arm64 kernel. and yes, armv8l really is armv7, not aarch64.

https://bugs.launchpad.net/ubuntu/+source/clang/+bug/1827175
^ links to:
https://stackoverflow.com/q/27121199/608639

for armhf with a 32-bit emulated kernel, I get:
armv7l-unknown-linux-gnueabihf
Comment 170 Dmitry Selyutin 2023-10-24 06:34:04 BST
Folks, I don't have any suitable arm or aarch64 device which I could sacrifice for running our env, so you'll have to find it out. I'd say that arm/aarch64 support is not something I expected.
Comment 171 Dmitry Selyutin 2023-10-24 06:45:32 BST
(In reply to Jacob Lifshay from comment #167)
> (In reply to Luke Kenneth Casson Leighton from comment #166)
> > jacob see #1066 reduce the mem block down to 1<<29 please
> 
> I'm assuming you meant bug #1173.
> > 
> > dmitry the return result is "-1" but is coming out at 0xffffffffff...

...which is exactly the expected result when unsigned integer is used. I think the result can just use long instead of ulong.

> 
> I would guess the issue is that uname is being used, but what you actually
> need is the arch of the user-space executable, not the kernel, since Luke
> seems to have a armhf user-space and aarch64 kernel. after some
> experimentation, it looks like you can use:
> python3 -c 'import sysconfig;
> print(sysconfig.get_config_var("HOST_GNU_TYPE"))'

I'd take a look at this:
platform.architecture()[0]
sys.maxsize > 2**32
Comment 172 Jacob Lifshay 2023-10-24 06:53:25 BST
(In reply to Dmitry Selyutin from comment #171)
> > I would guess the issue is that uname is being used, but what you actually
> > need is the arch of the user-space executable, not the kernel, since Luke
> > seems to have a armhf user-space and aarch64 kernel. after some
> > experimentation, it looks like you can use:
> > python3 -c 'import sysconfig;
> > print(sysconfig.get_config_var("HOST_GNU_TYPE"))'
> 
> I'd take a look at this:
> platform.architecture()[0]
> sys.maxsize > 2**32

platform.architecture() on my phone returns:
('64bit', 'ELF')
which has no mention of arm. so imo not very useful.

presumably aarch64 systems can have both armhf and armel multiarch. x86_64 likewise can have both i686 and x32.
Comment 173 Jacob Lifshay 2023-10-24 06:58:29 BST
(In reply to Dmitry Selyutin from comment #170)
> Folks, I don't have any suitable arm or aarch64 device which I could
> sacrifice for running our env, so you'll have to find it out. I'd say that
> arm/aarch64 support is not something I expected.

I think it's fine to say we're not supporting arm as part of this bug, luke will just have to use his laptop. that said, it would be nice to support arm at some point.
Comment 174 Dmitry Selyutin 2023-10-24 07:00:58 BST
(In reply to Jacob Lifshay from comment #172)
> (In reply to Dmitry Selyutin from comment #171)
> > > I would guess the issue is that uname is being used, but what you actually
> > > need is the arch of the user-space executable, not the kernel, since Luke
> > > seems to have a armhf user-space and aarch64 kernel. after some
> > > experimentation, it looks like you can use:
> > > python3 -c 'import sysconfig;
> > > print(sysconfig.get_config_var("HOST_GNU_TYPE"))'
> > 
> > I'd take a look at this:
> > platform.architecture()[0]
> > sys.maxsize > 2**32
> 
> platform.architecture() on my phone returns:
> ('64bit', 'ELF')
> which has no mention of arm. so imo not very useful.
> 
> presumably aarch64 systems can have both armhf and armel multiarch. x86_64
> likewise can have both i686 and x32.

Yes I know. You have to check both arch and some Python executable information simultaneously. That's why you need to check not only platform.platform() but also sys.maxsize (as a cheap way).
Comment 175 Jacob Lifshay 2023-10-24 07:12:24 BST
(In reply to Dmitry Selyutin from comment #174)
> > > > python3 -c 'import sysconfig;
> > > > print(sysconfig.get_config_var("HOST_GNU_TYPE"))'

> Yes I know. You have to check both arch and some Python executable
> information simultaneously. That's why you need to check not only
> platform.platform() but also sys.maxsize (as a cheap way).

but checking platform.platform() just uses uname (see source code), and combining that with sys.maxsize can't distinguish between armhf/armel or i686/x32 afaict...i know i686 and x32 have different syscall ABIs and maybe armhf/armel too, so it is information you need to know to get it right.

the method I suggested using python's sysconfig module gets its info from autotools (config.guess/config.sub) via python's config.h and makefiles, so should contain enough to know the exact ABI.
Comment 176 Jacob Lifshay 2023-10-24 07:14:52 BST
(In reply to Jacob Lifshay from comment #175)
> but checking platform.platform() just uses uname (see source code),

https://github.com/python/cpython/blob/v3.7.17/Lib/platform.py#L1334
Comment 177 Dmitry Selyutin 2023-10-24 07:20:21 BST
The idea is that with uname report of 64 bit OS and 32-bit userspace you can switch appropriately.
Comment 178 Jacob Lifshay 2023-10-24 07:22:55 BST
(In reply to Dmitry Selyutin from comment #177)
> The idea is that with uname report of 64 bit OS and 32-bit userspace you can
> switch appropriately.

yes, I'm saying there may be *multiple* 32-bit userspace ABIs each with a separate syscall ABI. just knowing that user-space is 32-bit doesn't necessarily tell you how to decide which ABI you need.
Comment 179 Dmitry Selyutin 2023-10-24 07:27:12 BST
No, it doesn't affect ABI of syscalls. The only ABI in Linux syscalls we have is OABI, which I don't think modern ARM should use. Same for x86: you don't have different ABIs except for x86/x86_64/x32 (IIRC the latter is dead already as well).
Comment 180 Dmitry Selyutin 2023-10-24 07:27:57 BST
The only ABI => the only additional ARM ABI
Comment 181 Jacob Lifshay 2023-10-24 07:34:10 BST
(In reply to Dmitry Selyutin from comment #179)
> No, it doesn't affect ABI of syscalls. The only ABI in Linux syscalls we
> have is OABI, which I don't think modern ARM should use. Same for x86: you
> don't have different ABIs except for x86/x86_64/x32 (IIRC the latter is dead
> already as well).

ok. there's also big-endian arm, but i think we can ignore that.
Comment 182 Luke Kenneth Casson Leighton 2023-10-24 07:40:13 BST
(In reply to Jacob Lifshay from comment #173)

> I think it's fine to say we're not supporting arm as part of this bug, luke
> will just have to use his laptop. 

i'm right here dmitry, please do try to avoid referring to people
in 3rd person, it is normally considered rude? i do appreciate you
are discussing with jacob and not expecting me to be awake at 7am UK

> that said, it would be nice to support arm
> at some point.

indeed. annoying as it is to have a standard hardware and software
platform that decision was made for exactly this reason: to keep
the scope of work down to what NLnet can afford.
Comment 183 Jacob Lifshay 2023-10-24 07:48:07 BST
(In reply to Luke Kenneth Casson Leighton from comment #182)
> (In reply to Jacob Lifshay from comment #173)
> 
> > I think it's fine to say we're not supporting arm as part of this bug, luke
> > will just have to use his laptop.

I hope you're ok with that.

> i'm right here dmitry,

I think you mean jacob? you're replying to me...

> please do try to avoid referring to people
> in 3rd person, it is normally considered rude?

it depends? I was replying to Dmitry, so since I wasn't directly talking to you, imo 3rd person is appropriate (like how i just referred to Dmitry in the 3rd person).
Comment 184 Luke Kenneth Casson Leighton 2023-10-24 08:05:21 BST
(In reply to Jacob Lifshay from comment #183)

> 
> I think you mean jacob? you're replying to me...

click. yes. sorry for the confusion (dmitry)

> > please do try to avoid referring to people
> > in 3rd person, it is normally considered rude?
> 
> it depends? I was replying to Dmitry, so since I wasn't directly talking to
> you, imo 3rd person is appropriate (like how i just referred to Dmitry in
> the 3rd person).

the usual way is to say in advance, "i am aware you are there and
participating, i am about to dscuss you in the 3rd person, please
do not take offense"

which is so long it is only worthwhile for detailed discussuon, 
rather than just simply assume (on a delay) that it is a normal
conversation
Comment 185 Dmitry Selyutin 2023-10-24 11:38:06 BST
I kinda lost with the recent comments. Luke, I do not get what you try to tell me, and have no idea what seemed to be rude with my words (especially that you were replying to Jacob's comment).
Comment 186 Luke Kenneth Casson Leighton 2023-10-24 13:34:57 BST
(In reply to Dmitry Selyutin from comment #185)
> I kinda lost with the recent comments. Luke, I do not get what you try to
> tell me, 

nothing!

> and have no idea what seemed to be rude with my words 

you weren't

> (especially that you were replying to Jacob's comment).

... and not realising it. yes, sorry for the miscommunication.
Comment 187 Dmitry Selyutin 2023-10-24 19:27:16 BST
Guys, I've pinned the Linux kernel source.

https://git.libre-soc.org/?p=dev-env-setup.git;a=commitdiff;h=db25adc0c551626a9d2a4ddfa05f3ca9c8ca0bef

This is done as a single command so that we clone at depth 1 of a specific tag.
Comment 188 Dmitry Selyutin 2023-10-25 17:10:24 BST
Why is 1173 listed as blocker for this task? It is not. In fact, the relationship is different.
Comment 189 Dmitry Selyutin 2023-10-25 17:10:46 BST
s/different/opposite/
Comment 190 Dmitry Selyutin 2023-10-25 17:24:09 BST
After some thought, they don't even have blocker relationship. Transparent memory mapping translation just enables some system calls; however, this mechanism is not mandatory for doing system calls. I see no reason for that task to be a blocker.
Comment 191 Jacob Lifshay 2023-10-25 18:50:15 BST
(In reply to Dmitry Selyutin from comment #188)
> Why is 1173 listed as blocker for this task?

because the original plan was to support `read`/`write`, which need a pointer to memory. MemMMap.get_ctypes provides that pointer.

https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/decoder/isa/mem.py;h=cad3d052a38252ebf0e1cf3b8b41deac813e269e;hb=49cd5029f5aa997d80bfcdd5dbaaa873913f8b93#l383
Comment 192 Luke Kenneth Casson Leighton 2023-10-25 18:53:40 BST
(In reply to Dmitry Selyutin from comment #187)
> Guys, I've pinned the Linux kernel source.
> 
> https://git.libre-soc.org/?p=dev-env-setup.git;a=commitdiff;
> h=db25adc0c551626a9d2a4ddfa05f3ca9c8ca0bef
> 
> This is done as a single command so that we clone at depth 1 of a specific
> tag.

fantastic.

(In reply to Dmitry Selyutin from comment #188)

> Why is 1173 listed as blocker for this task? It is not. In fact, the
> relationship is different.

ignore it.

i do need you to do comment #165 though. the project coding
standards require absolute (full) import paths.  relative
paths are prohibited.
Comment 193 Luke Kenneth Casson Leighton 2023-10-25 18:55:05 BST
(In reply to Jacob Lifshay from comment #191)
> (In reply to Dmitry Selyutin from comment #188)
> > Why is 1173 listed as blocker for this task?
> 
> because the original plan was to support `read`/`write`, which need a
> pointer to memory. MemMMap.get_ctypes provides that pointer.

happy for that to be a "nice to have" although i am genuinely
curious to see if it works, i will authorize payment when
comment #165 is dealt with.
Comment 194 Jacob Lifshay 2023-10-25 19:12:42 BST
(In reply to Luke Kenneth Casson Leighton from comment #193)
> happy for that to be a "nice to have" although i am genuinely
> curious to see if it works, i will authorize payment when
> comment #165 is dealt with.

MemMMap.get_ctypes does work, I have tests for it. it has not been integrated into the syscall framework yet (probably part of a later task)

https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/decoder/isa/test_mem.py;h=e57d199148a86de07f67645bb009075005e9f2f3;hb=a5d50b0759a5c9196ae0b10441905a5bbecaabce#l82
Comment 195 Dmitry Selyutin 2023-10-25 21:27:19 BST
https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=066fe2eae8514911ee8ff882ab7a8c98642662a7

Introduced an architecture detection, this should perform better on multilib configurations. From now on, the Dispatcher class expects a sanitized architecture name; to be sure, use architecture() function. Changed imports.
Comment 196 Luke Kenneth Casson Leighton 2023-10-25 22:11:40 BST
brilliant work everyone, we're definitely done here. mmap syscall
perhaps under bug #983 jacob?
RFP time...
Comment 197 Jacob Lifshay 2023-10-25 22:22:45 BST
(In reply to Luke Kenneth Casson Leighton from comment #196)
> brilliant work everyone, we're definitely done here. mmap syscall
> perhaps under bug #983 jacob?

yup, that's the plan! (busy trying to recover luks keys from a corrupted ceph-mon database, I may be busy for a while)
Comment 198 Luke Kenneth Casson Leighton 2023-10-26 21:29:38 BST
    def add_case(self, prog, initial_regs=None, initial_sprs=None,
                 initial_cr=0, initial_msr=DEFAULT_MSR,
                 initial_mem=None,

sorry i missed this.  this *has* to be initial_msr=None
followed in ISACaller "if initial_msr is None: initial_msr=DEFAULT_MSR"

it is *not* ok to change the initial_msr to something that cannot
be overridden. jacob can you remember the bugreport where this was
discussed?
Comment 199 Dmitry Selyutin 2023-10-26 22:30:37 BST
(In reply to Luke Kenneth Casson Leighton from comment #198)
>     def add_case(self, prog, initial_regs=None, initial_sprs=None,
>                  initial_cr=0, initial_msr=DEFAULT_MSR,
>                  initial_mem=None,
> 
> sorry i missed this.  this *has* to be initial_msr=None
> followed in ISACaller "if initial_msr is None: initial_msr=DEFAULT_MSR"
> 
> it is *not* ok to change the initial_msr to something that cannot
> be overridden. jacob can you remember the bugreport where this was
> discussed?

Jacob, I think this should be handled by you. First, it seems you're better familiar with the rationale (I saw none; all I see is that default value is 0, and nothing really expects None anywhere). Second, I don't even use add_case at all, I haven't touched this place. Third, I pass initial MSR value from the test directly.
Comment 200 Jacob Lifshay 2023-10-26 23:28:37 BST
(In reply to Jacob Lifshay from comment #197)
> yup, that's the plan! (busy trying to recover luks keys from a corrupted
> ceph-mon database, I may be busy for a while)

Finally got ceph up and working again after writing a python script to try to extract data from a corrupted rocksdb. took me like 20hr of work. I now backed up all my ceph stuff and added keys I know to my luks partitions.

(In reply to Luke Kenneth Casson Leighton from comment #198)
> sorry i missed this.  this *has* to be initial_msr=None
> followed in ISACaller "if initial_msr is None: initial_msr=DEFAULT_MSR"

ok, I can do that.

> it is *not* ok to change the initial_msr to something that cannot
> be overridden.

I don't see how that's any easier or harder to override...if you need a different MSR for everything, just change DEFAULT_MSR.

> jacob can you remember the bugreport where this was
> discussed?

some searching led to:
https://bugs.libre-soc.org/show_bug.cgi?id=1072
Comment 201 Jacob Lifshay 2023-10-26 23:46:20 BST
(In reply to Jacob Lifshay from comment #200)
> (In reply to Luke Kenneth Casson Leighton from comment #198)
> > sorry i missed this.  this *has* to be initial_msr=None
> > followed in ISACaller "if initial_msr is None: initial_msr=DEFAULT_MSR"
> 
> ok, I can do that.

done:
https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=21f95f5bb243c937aed9f9ef28605f20b33b7b0e
Comment 202 Luke Kenneth Casson Leighton 2023-10-27 01:40:15 BST
(In reply to Jacob Lifshay from comment #200)

> Finally got ceph up and working again after writing a python script to try
> to extract data from a corrupted rocksdb.

now you know never to use rocksdb ever again.
good idea to pay attention to howard chu's advice here.

> (In reply to Luke Kenneth Casson Leighton from comment #198)

> I don't see how that's any easier or harder to override...if you need a
> different MSR for everything, just change DEFAULT_MSR.

...via and *only* via the mechanism of bug #1173
(not 1072)