Here's a preliminary patch for sbus slot probing.
This can be used for the preliminary dbri device patch, see my dbri-pre1 branch at github: https://github.com/breuerr/qemu/tree/dbri-pre1 That branch also has a rewritten fcode rom to avoid the use of the obsolete intr forth word. Use the SS-20 machine to get the dbri device.
Todo: non-faulting reads so that an empty slot can be probed extend to probe other (all?) slots as well only add the slot E range for SS-20, but not SS-10
Is there any existing code for sparc32 which does a non-faulting read? It looks like even cpeek doesn't try to catch any faults.
Bob
Index: drivers/sbus.c =================================================================== --- drivers/sbus.c (revision 1046) +++ drivers/sbus.c (working copy) @@ -451,11 +451,36 @@ static void sbus_probe_slot_ss10(unsigned int slot, uint64_t base) { + ucell fcode; + unsigned char start; + // OpenBIOS and Qemu don't know how to do Sbus probing switch(slot) { case 2: // SUNW,tcx ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx"); break; + case 0xe: // dbri + fcode = ofmem_map_io(base, 0x1000); + // TODO: non-faulting read + start = *(unsigned char*)fcode; + if (start == 0xfd || start == 0xf1) { + push_str("/iommu/sbus"); + fword("select-dev"); + fword("new-device"); + push_str(NULL); + PUSH(0); // offset + PUSH(slot); // space + push_str("encode-unit"); + fword("$call-parent"); + fword("set-args"); + PUSH(fcode); + PUSH(1); + fword("byte-load"); + fword("finish-device"); + fword("unselect-dev"); + } + ofmem_unmap(fcode, 0x1000); + break; case 0xf: // le, esp, bpp, power-management ob_macio_init(slot, base, 0); // Power management (APC) XXX should not exist @@ -534,6 +559,7 @@ { 1, 0, 0xe10000000ULL, 0x10000000,}, { 2, 0, 0xe20000000ULL, 0x10000000,}, { 3, 0, 0xe30000000ULL, 0x10000000,}, + [0xe] = { 0xe, 0, 0xee0000000ULL, 0x10000000,}, [0xf] = { 0xf, 0, 0xef0000000ULL, 0x10000000,}, };
On 15/08/11 16:01, Bob Breuer wrote:
Here's a preliminary patch for sbus slot probing.
Great work indeed :)
This can be used for the preliminary dbri device patch, see my dbri-pre1 branch at github: https://github.com/breuerr/qemu/tree/dbri-pre1 That branch also has a rewritten fcode rom to avoid the use of the obsolete intr forth word. Use the SS-20 machine to get the dbri device.
Todo: non-faulting reads so that an empty slot can be probed extend to probe other (all?) slots as well only add the slot E range for SS-20, but not SS-10
Is there any existing code for sparc32 which does a non-faulting read? It looks like even cpeek doesn't try to catch any faults.
Not that I know of. It looks as if there may be some work that needs to be done in qemu in order for this to happen as per the comment in hw/sun4m_iommu.c:
case IOMMU_ARBEN: // XXX implement SBus probing: fault when reading unmapped // addresses, fault cause and address stored to MMU/IOMMU s->regs[saddr] = (val & IOMMU_ARBEN_MASK) | IOMMU_MID; break;
I have a feeling that qemu invokes a known trap for unmapped memory, so it could be that given we know the SBus range we could just assume that any traps occurring during a read to that range is a failed probe?
Bob
Index: drivers/sbus.c
--- drivers/sbus.c (revision 1046) +++ drivers/sbus.c (working copy) @@ -451,11 +451,36 @@ static void sbus_probe_slot_ss10(unsigned int slot, uint64_t base) {
- ucell fcode;
- unsigned char start;
// OpenBIOS and Qemu don't know how to do Sbus probing switch(slot) { case 2: // SUNW,tcx ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx"); break;
- case 0xe: // dbri
fcode = ofmem_map_io(base, 0x1000);
// TODO: non-faulting read
start = *(unsigned char*)fcode;
if (start == 0xfd || start == 0xf1) {
See is_fcode() in libopenbios/fcode_load.c.
push_str("/iommu/sbus");
fword("select-dev");
fword("new-device");
push_str(NULL);
PUSH(0); // offset
PUSH(slot); // space
push_str("encode-unit");
fword("$call-parent");
fword("set-args");
PUSH(fcode);
PUSH(1);
fword("byte-load");
fword("finish-device");
fword("unselect-dev");
}
ofmem_unmap(fcode, 0x1000);
break; case 0xf: // le, esp, bpp, power-management ob_macio_init(slot, base, 0); // Power management (APC) XXX should not exist
@@ -534,6 +559,7 @@ { 1, 0, 0xe10000000ULL, 0x10000000,}, { 2, 0, 0xe20000000ULL, 0x10000000,}, { 3, 0, 0xe30000000ULL, 0x10000000,},
- [0xe] = { 0xe, 0, 0xee0000000ULL, 0x10000000,}, [0xf] = { 0xf, 0, 0xef0000000ULL, 0x10000000,}, };
The only other thing I'd like to see, as you mention, is the probe moved into a separate function which can be called from the appropriate _init() functions. I'd be interested to follow the discussion related to handling the various traps that occur during a fault access on this thread as you progress.
ATB,
Mark.
On Fri, Aug 19, 2011 at 8:44 PM, Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk wrote:
On 15/08/11 16:01, Bob Breuer wrote:
Here's a preliminary patch for sbus slot probing.
Great work indeed :)
This can be used for the preliminary dbri device patch, see my dbri-pre1 branch at github: https://github.com/breuerr/qemu/tree/dbri-pre1 That branch also has a rewritten fcode rom to avoid the use of the obsolete intr forth word. Use the SS-20 machine to get the dbri device.
Todo: non-faulting reads so that an empty slot can be probed extend to probe other (all?) slots as well only add the slot E range for SS-20, but not SS-10
Is there any existing code for sparc32 which does a non-faulting read? It looks like even cpeek doesn't try to catch any faults.
Not that I know of. It looks as if there may be some work that needs to be done in qemu in order for this to happen as per the comment in hw/sun4m_iommu.c:
case IOMMU_ARBEN: // XXX implement SBus probing: fault when reading unmapped // addresses, fault cause and address stored to MMU/IOMMU s->regs[saddr] = (val & IOMMU_ARBEN_MASK) | IOMMU_MID; break;
I have a feeling that qemu invokes a known trap for unmapped memory, so it could be that given we know the SBus range we could just assume that any traps occurring during a read to that range is a failed probe?
The documentation is pretty weak in this area, the comments above are just my guesses.
Bob
Index: drivers/sbus.c
--- drivers/sbus.c (revision 1046) +++ drivers/sbus.c (working copy) @@ -451,11 +451,36 @@ static void sbus_probe_slot_ss10(unsigned int slot, uint64_t base) {
- ucell fcode;
- unsigned char start;
// OpenBIOS and Qemu don't know how to do Sbus probing switch(slot) { case 2: // SUNW,tcx ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx"); break;
- case 0xe: // dbri
- fcode = ofmem_map_io(base, 0x1000);
- // TODO: non-faulting read
- start = *(unsigned char*)fcode;
- if (start == 0xfd || start == 0xf1) {
See is_fcode() in libopenbios/fcode_load.c.
- push_str("/iommu/sbus");
- fword("select-dev");
- fword("new-device");
- push_str(NULL);
- PUSH(0); // offset
- PUSH(slot); // space
- push_str("encode-unit");
- fword("$call-parent");
- fword("set-args");
- PUSH(fcode);
- PUSH(1);
- fword("byte-load");
- fword("finish-device");
- fword("unselect-dev");
- }
- ofmem_unmap(fcode, 0x1000);
- break;
case 0xf: // le, esp, bpp, power-management ob_macio_init(slot, base, 0); // Power management (APC) XXX should not exist @@ -534,6 +559,7 @@ { 1, 0, 0xe10000000ULL, 0x10000000,}, { 2, 0, 0xe20000000ULL, 0x10000000,}, { 3, 0, 0xe30000000ULL, 0x10000000,},
- [0xe] = { 0xe, 0, 0xee0000000ULL, 0x10000000,},
[0xf] = { 0xf, 0, 0xef0000000ULL, 0x10000000,}, };
The only other thing I'd like to see, as you mention, is the probe moved into a separate function which can be called from the appropriate _init() functions. I'd be interested to follow the discussion related to handling the various traps that occur during a fault access on this thread as you progress.
ATB,
Mark.
-- Mark Cave-Ayland - Senior Technical Architect PostgreSQL - PostGIS Sirius Corporation plc - control through freedom http://www.siriusit.co.uk t: +44 870 608 0063
Sirius Labs: http://www.siriusit.co.uk/labs
-- OpenBIOS http://openbios.org/ Mailinglist: http://lists.openbios.org/mailman/listinfo Free your System - May the Forth be with you
Mark Cave-Ayland wrote:
On 15/08/11 16:01, Bob Breuer wrote:
Here's a preliminary patch for sbus slot probing.
Great work indeed :)
This can be used for the preliminary dbri device patch, see my dbri-pre1 branch at github: https://github.com/breuerr/qemu/tree/dbri-pre1 That branch also has a rewritten fcode rom to avoid the use of the obsolete intr forth word. Use the SS-20 machine to get the dbri device.
Todo: non-faulting reads so that an empty slot can be probed extend to probe other (all?) slots as well only add the slot E range for SS-20, but not SS-10
Is there any existing code for sparc32 which does a non-faulting read? It looks like even cpeek doesn't try to catch any faults.
Not that I know of. It looks as if there may be some work that needs to be done in qemu in order for this to happen as per the comment in hw/sun4m_iommu.c:
case IOMMU_ARBEN: // XXX implement SBus probing: fault when reading unmapped // addresses, fault cause and address stored to MMU/IOMMU s->regs[saddr] = (val & IOMMU_ARBEN_MASK) | IOMMU_MID; break;
I have a feeling that qemu invokes a known trap for unmapped memory, so it could be that given we know the SBus range we could just assume that any traps occurring during a read to that range is a failed probe?
Looking at the SRMMU control bits, I should be able to just toggle NF to ignore faults. Not sure if I'll then need to check for an mmu fault or sbus fault or both, but I've got an SS-20 here that I can check it against to verify if the emulated behavior matches the real behavior.
Bob
Index: drivers/sbus.c
--- drivers/sbus.c (revision 1046) +++ drivers/sbus.c (working copy) @@ -451,11 +451,36 @@ static void sbus_probe_slot_ss10(unsigned int slot, uint64_t base) {
- ucell fcode;
- unsigned char start;
// OpenBIOS and Qemu don't know how to do Sbus probing switch(slot) { case 2: // SUNW,tcx ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx"); break;
- case 0xe: // dbri
fcode = ofmem_map_io(base, 0x1000);
// TODO: non-faulting read
start = *(unsigned char*)fcode;
if (start == 0xfd || start == 0xf1) {
See is_fcode() in libopenbios/fcode_load.c.
From what I've read, the other start codes (f0, f2, f4) signify
alternate stride sizes, for example f2 (2-byte stride) could be a byte-wide rom on a 16-bit bus. Does byte-load handle a stride other than 1? Either way, it covers my use-case so I'll switch to using is_fcode.
push_str("/iommu/sbus");
fword("select-dev");
fword("new-device");
push_str(NULL);
PUSH(0); // offset
PUSH(slot); // space
push_str("encode-unit");
fword("$call-parent");
fword("set-args");
PUSH(fcode);
PUSH(1);
fword("byte-load");
fword("finish-device");
fword("unselect-dev");
}
ofmem_unmap(fcode, 0x1000);
break; case 0xf: // le, esp, bpp, power-management ob_macio_init(slot, base, 0); // Power management (APC) XXX should not exist
@@ -534,6 +559,7 @@ { 1, 0, 0xe10000000ULL, 0x10000000,}, { 2, 0, 0xe20000000ULL, 0x10000000,}, { 3, 0, 0xe30000000ULL, 0x10000000,},
- [0xe] = { 0xe, 0, 0xee0000000ULL, 0x10000000,}, [0xf] = { 0xf, 0, 0xef0000000ULL, 0x10000000,}, };
The only other thing I'd like to see, as you mention, is the probe moved into a separate function which can be called from the appropriate _init() functions. I'd be interested to follow the discussion related to handling the various traps that occur during a fault access on this thread as you progress.
If enabling the no-fault mmu mode works, I'll go with that. Otherwise I'd consider using setjmp, and then longjmp from the interrupt handler, but I'm not sure if that would work. Or is there already a usable throw/catch mechanism that would work from an interrupt?
Bob