Memory Map (S390): Difference between revisions

From OSDev.wiki
Jump to navigation Jump to search
[unchecked revision][unchecked revision]
Content added Content deleted
No edit summary
No edit summary
Line 28: Line 28:
</source>
</source>


Now there needs to be a function to "catch" the exceptions recognized by the processor:
<source lang="c">
<source lang="c">
/* Check if an address is valid - this only catches program exceptions to
/* Check if an address is valid - this only catches program exceptions to
Line 68: Line 69:
return r;
return r;
}
}
</source>

Some C compilers are known to crash or even ABEND during compilation if addresses of labels are taken via the && operator, alternatively using direct high-level assembler syntax:

<source lang="asm">
* HwCheckAddress
* IN:
* pointer to address to probe
*
ENTRY @ZHWCHKA
@ZHWCHKA DS 0H
SAVE (14,12),,@ZHWCHKA
LR R12,R15
USING @ZHWCHKA,12
LR R11,R1
* CATCHPSW address on R1
L R1,=A(CATCHPSW)
* Save address of TMPSAVE on R2
L R2,=A(TMPSAVE)
* And FLCPNPSW on R3
L R3,FLCPNPSW
*
MVC 0(8,R2),0(R3)
* ... use a new PSW to catch the exceptions
MVC 0(8,R3),0(R1)
* Probe the address, if it raises a PC exception then
* we will simply catch it and return 1
L R1,0(R11)
L R15,0(R1)
* rc = 0
MVC 0(8,R3),0(R2)
L R15,=F'0'
RETURN (14,12),RC=(15)
CATCHPCR DS 0H
* rc = 1
MVC 0(8,R3),0(R2)
L R15,=F'1'
RETURN (14,12),RC=(15)
LTORG
DROP 12
*
CATCHPSW DS 0D
DC X'020E0000'
DC A(AMBIT+CATCHPCR)
TMPSAVE DS 1D
</source>
</source>



Revision as of 00:18, 17 January 2022

The memory map on the S390 is very simple, the first 1024 (or 8192, if on z/Arch) bytes are used as PSA area. The IPL is loaded just after that said PSA.

Detecting memory

/* We are going to read in pairs of 1MiB and when we hit the memory limit we
 * will instantly catch the program exception and stop counting, then it's just
 * a matter of returning what we could count :) */
size_t s390_get_memsize(
    void)
{
    const uint8_t *probe = (const uint8_t *)0x0;
    while(1) {
        int r;
        /* Do a "probe" read */
        r = s390_address_is_valid(probe);
        if(r != 0) {
            kprintf("Done! %p\n", (uintptr_t)probe);
            break;
        }

        kprintf("Memory %p\n", (uintptr_t)probe);

        /* Go to next MiB */
        probe += 1048576;
    }
    return (size_t)probe;
}

Now there needs to be a function to "catch" the exceptions recognized by the processor:

/* Check if an address is valid - this only catches program exceptions to
 * determine if it's valid or not */
int s390_address_is_valid(
    volatile const void *probe)
{
    int r = 0;

    S390_PSW_DEFAULT_TYPE old_pc_psw;
#if (MACHINE >= M_ZARCH)
    struct s390x_psw pc_psw = {
        0x00040000 | S390_PSW_AM64, S390_PSW_DEFAULT_AMBIT, 0,
        (uint32_t)&&invalid
    };
#else
    struct s390_psw pc_psw = {
        0x000C0000, (uint32_t)&&invalid + S390_PSW_DEFAULT_AMBIT
    };
#endif

#if (MACHINE >= M_ZARCH)
    memcpy(&old_pc_psw, (void *)S390_FLCEPNPSW, sizeof(struct s390x_psw));
    memcpy((void *)S390_FLCEPNPSW, &pc_psw, sizeof(struct s390x_psw));
#else
    memcpy(&old_pc_psw, (void *)S390_FLCPNPSW, sizeof(struct s390_psw));
    memcpy((void *)S390_FLCPNPSW, &pc_psw, sizeof(struct s390_psw));
#endif

    *((volatile const uint8_t *)probe);
    goto end;
invalid:
    r = -1;
end:
#if (MACHINE >= M_ZARCH)
    memcpy((void *)S390_FLCEPNPSW, &old_pc_psw, sizeof(struct s390x_psw));
#else
    memcpy((void *)S390_FLCPNPSW, &old_pc_psw, sizeof(struct s390_psw));
#endif
    return r;
}

Some C compilers are known to crash or even ABEND during compilation if addresses of labels are taken via the && operator, alternatively using direct high-level assembler syntax:

* HwCheckAddress
* IN:
*    pointer to address to probe
*
         ENTRY @ZHWCHKA
@ZHWCHKA DS 0H
         SAVE (14,12),,@ZHWCHKA
         LR R12,R15
         USING @ZHWCHKA,12
         LR R11,R1
* CATCHPSW address on R1
         L R1,=A(CATCHPSW)
* Save address of TMPSAVE on R2
         L R2,=A(TMPSAVE)
* And FLCPNPSW on R3
         L R3,FLCPNPSW
*
         MVC 0(8,R2),0(R3)
* ... use a new PSW to catch the exceptions
         MVC 0(8,R3),0(R1)
* Probe the address, if it raises a PC exception then
* we will simply catch it and return 1
         L R1,0(R11)
         L R15,0(R1)
* rc = 0
         MVC 0(8,R3),0(R2)
         L R15,=F'0'
         RETURN (14,12),RC=(15)
CATCHPCR DS 0H
* rc = 1
         MVC 0(8,R3),0(R2)
         L R15,=F'1'
         RETURN (14,12),RC=(15)
         LTORG
         DROP 12
*
CATCHPSW DS 0D
         DC X'020E0000'
         DC A(AMBIT+CATCHPCR)
TMPSAVE  DS 1D

See also =

Source code