#Crescent
1 messages Β· Page 2 of 1
its possible, I have done some manual testing with the fields but that very likely didn't cover a lot of cases
Yeah I barely have test cases for those
And frankly I dont remember how edge cases are supposed to work there
the current field read/write logic that I have isn't even that complex, I don't see anything immediately wrong with it (though ofc it doesn't mean that its correct either)
ig if I would add uacpi maybe slightly more properly than last time I could try comparing the writes/reads again
That would be the easiest thing to do
Diffing the io
Or u can look at e.g. what _REG does
Maybe notice something suspicious that can misbehave in qacpi
Btw did you figure it out?
no I didn't try it yet, I have been busy implementing proper mmap/munmap/mprotect 
Thats probably more useful than figuring out firmware issues
I found out at least one possibly related minor difference and its that I register the ec handler after initializing the namespace
I didn't try if that makes any difference tho
You do it before or after depending on whether you've been given an ecdt
And yes it makes a huge diff
Because it does OSYS checks in REG potentially
Basically hw with ecdt have almost no op _REG
Hw without ecdt has huge REG usually
yeah I already do it before even loading the namespace if there is an ecdt
How do u run REG before loading the namespace?
wait no yeah I misremembered lol
Lmfao
before initializing the namespace
ah right, it only discovers the ec before initializing but doesn't install the addr space handler
nvm then
also other thing that I found now by comparing the test runner output when feeding my dsdt/ssdts is that some fields are read in different order (maybe its related to the fact that I don't immediately evaluate fields to their values)
Wdym by immediately?
or actually idk, in ```
OperationRegion (ICLK, SystemMemory, (SBRG + ((ICKP << 0x10) + 0x8000)), 0x40)
Ah I see
I dont think its specified by the spec
But I think nt does left to right too
Do u think it matters in this case?
I'd hope it doesn't, that was just one difference that I found
are SBRG and ICKP registers?
As its the simplest way
Ye
lmao wtf
Ikr
though to be fair I don't think the difference between uacpi comes from that because the other operand of each of the exprs in there is an integer
uacpi
1 0X44AC4EAD = 0X9B
1 0X44AB9830 = 0X9B
1 0X44AC4334 = 0X9B
1 0X44AC4335 = 0X9B
1 0X44AC4336 = 0X9B
1 0X44AC4337 = 0X9B
1 0X44AC4567 = 0X9B
1 0X44AC4568 = 0X9B
qacpi
1 0X44AC4EAD = 0X9B
1 0X44AB9830 = 0X9B
1 0X44AC4567 = 0X9B
1 0X44AC4568 = 0X9B
1 0X44AC4334 = 0X9B
1 0X44AC4335 = 0X9B
1 0X44AC4336 = 0X9B
1 0X44AC4337 = 0X9B
or actually it probably is 
but like idk how exactly
actually wait, so uacpi evaluates the field right when it sees it and not when its used in an expr?
Well depends on what u mean
But I think so
If there's an AddOp(lhs, ...)
Where lhs is a field
Its evaluated right away yes
as in (SBRG + ((ICKP << 0x10) + 0x8000)) when it first sees SBRG it evaluates it before pushing the value to the stack and continuing evaluating the other half of it
yeah that probably explains it, ig I should do that too instead of pushing field object to the stack
I think its supposed to be kinda transparent in that way
Cool lemme know if that somehow fixes bogus events
yeah Ill do, there are still a lot more in the test runner log that Ill have to manually compare because there's other trace info in between 
I think uacpi would automatically convert that field name into a fake FieldReadOp
So the addop won't even know there was a field
Makes sense
qwinci are u a crossont
yes 
omg π±
after that change at least the reads/writes done during the namespace load match, for the init I am not sure as the order is different (though I did spot one difference regarding the ec's reg, it sets OSTY to 7 whereas with uacpi it sets it to 1)
Huh, interesting
Why is your init order different
Oh also uacpi test runner disables some osi strings I think for testing
I do it top down, no particular reason as for why
doesn't uacpi do it depth first?
By top down u mean bfs?
Can u try commenting out the osi interace disabling code btw
(In uacpi test runner)
yeah Ill try, that might be it as it does a check on the disabled osi string
Ye that would make sense
a
b c
d e f g
``` I would do `a, b, d, e, c, f, g`
I wonder why is it different then 
π
actually wait, I need to push the children in the opposite order that's probably why (so basically rn it inits the last child first)
which might be bad if it depends on the childs before it being initialized already
back to comparing the reads/writes ig
Uacpi had this problem
And it did break some hw iirc
now ig its time to finally retest it, I didn't check all of the init addresses but I think they match now
I also got rid of reads from fields marked as preserved if the bit offset within an access size is zero and the bit width == access size in bits
So it was just top down vs bottom up?
yes
I hope that it works now because if it doesn't I have no idea what to do about it
Btw a funny thing about fields
Ipmi, smbus and others utilize a read-then-write approach
What this means is
Local0 = FILD = Local0
Writes the request to FILD
The buffer that gets written is modified with the response right away
is that evaluated as (Local0 = FILD) = Local0 in aml?
And that rvalue gets stored to local0
ah no, i misunderstood
Basically as Store(Store(Local0, FILD), Local0)
so Local0 = (FILD = Local0)
does the aml compiler handle that?
In c++
You handle that im afraid 
Im working on that in uacpi right now
how do you even handle that lol
do you just read the field before assigning to it and then store the value read at the start to the target/push to the stack?
Well ill have the address space write handler also modify the input I guess
The field is never read at all
The contents of local0 are written to the field
And local0 is magically modified with the response
now write a constant instead 
Or rather, a write to that field magically returns a response
Luckily not a thing in aml lol
FLD = Zero?
ah, so the addr space handler basically returns the response that's pushed as the result of the assignment?
Yup
temporary one i assume?
Yeah
It exists for the duration of the op
All those protocols have different buffer sizes they expect on input so u have to dynamically allocate and memcpy anyway
So it doesnt matter if aml writes a small value
I don't think the ec thing happens now btw, at least so far it hasn't occurred
Good find
Uapci had this bug as well early on
Its only intuitive to push at the front
I just hope that the field related change didn't break anything
basically now it immediately reads the field when it encounters a name that resolves to a field
yeah I don't think I did, I specifically made it push the field object itself if a supername is expected (basically the same way it works for methods)
Like method names?
yes
Ah
anyway now ig its time to get back to the fun stuff after spending 5h on this annoying thing mostly consisting of comparing logs 
I were starting to implement ppoll
though maybe I should start with signals first because they kinda interact with everything else

signals 
struct sigaction act {
.sa_handler = [](int num) {
printf("SIGSEGV handler AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA %d\n", num);
while (true) {
asm volatile("");
}
},
.sa_mask {},
.sa_flags {},
.sa_restorer {}
};
sigaction(SIGSEGV, &act, nullptr);
*reinterpret_cast<volatile int*>(0) = 0;
now I just have to make tgkill ig, I already made a basic skeleton for it but it needs a pid to process table and I didn't add that yet
and sigrestore but that shouldn't be hard
Signals my behated
lol
I mean yeah they are kinda weird but at the same time I think they are kinda cool
now ig its time for the poll, I have the basic signal stuff including tgkill/kill implemented (apart from SIGSTOP/SIGCONT but I don't want to handle that rn)
I just hope that I didn't introduce any deadlocks by using mutexes to protect the signal stuff instead of irq disabling spinlocks 
I think its fine as the mutex is only taken inside sigaction and whatever else like that and inside the pre-emption timer but only if it came from userspace and a thread can't be both in sigaction and in userspace at the same time
idk if its really necessary to even protect the signal context from concurrent access by multiple threads but I couldn't find any info about the thread safety of sigaction
or signal safety too ig as there could be a signal that it installs handler for being triggered at the same time
well its specified to be signal safe so ig I need the mutex anyway
I think I fixed the scheduler + event stuff now hopefully (previously it had weird workarounds), I don't want to touch it anymore 
at least it works with 18 cores + 80 spawned windows in different processes
"abandon all hope ye who enter here"
lol
there are many different locks that interact with each other and are acquired in different order in different parts of the code
one per-thread lock that protects it from being moved to an other cpu, one per-thread lock to protect its run status and some other locks like per-scheduler sleeping threads list lock
now I think I can get back to the poll again 3rd time
as I implemented a wait multiple events function too, I hope that it works
also one thing which I have no idea how to implement is syscalls that are supposed to return EINTR if interrupted by a signal
every wait point has to be ready to be cancelled by the reception of a signal (or the presence of one already queued)
ah, yeah I guess that isn't too bad then as I'd just have to keep track whether a thread is inside an interruptible syscall and then if a signal is queued check check that and unblock the thread if its blocked (and set some marker inside it to tell it the wake reason ig)
bash kinda works, though if I type anything nothing appears
it does display the prompt again when I press enter tho which is weird
did you implement tty echoing if its in raw mode (readline)
I didn't implement tty at all
I just did this, then in poll if there is input in input_events I return POLLIN and in read I just get inputs from the queue and convert them to characters
and in stdout vnode's write I just print whatever is put there using the kernel print
ah right is bash expecting the terminal to do the echoing?
No, its raw mode I think
I wonder what is it then
at least it seems to be working otherwise, I typed echo hello from crescent and pressed enter
I could be retarded but I distinctly remember bash doing write(2) with the char and enabling echoing causing the char to appear twice
you can probably look at termios to see what it wants

apparently it just wanted a somewhat sane termios out of TCGETS and now it mostly displays it correctly (except sometimes there are random spaces between the characters)
actually nvm that was just because I accidentally gave it a winsize with 18 cols lol
btw @dire galleon I pushed the vmx code a few days ago, though the userspace vm thing is still the same way as it as a month ago (the kernel code is in https://github.com/Qwinci/crescent/blob/main/src/arch/x86/dev/vmx.cpp, the syscalls start from here https://github.com/Qwinci/crescent/blob/main/src/sys/syscalls.cpp#L1885 and the generic abstract vm class is in https://github.com/Qwinci/crescent/blob/main/src/dev/evm.hpp)
thanks for the ping! I'm keen to have a read through this
I should add some comments to it though, not everything of it is self-explanatory (though the sdm does a decent job at explaining most of the things)
and there is also generic x86 instruction emulation code in that file that I want to move out from there because it can be shared between different virtualization impls
whoa crescent has a hypervisor
for vmx (intel's virtualization thing, amd has svm) yes, though the userspace thing that uses it sucks lol
I mean it can display the first line that seabios prints to vga but that's as far as it gets
still pretty damn cool
yeah agreed, thats pretty cool
[desktop]: connection accepted
[kernel][x86]: pagefault caused by userspace read from FFFFFFFFE5A4B050 (instruction fetch)
at FFFFFFFFE5A4B050
[kernel][x86]: sending SIGSEGV to evm (thread evm)
[kernel][signal]: killing thread evm because of unhandled signal 11
[kernel][sched]: destroying exited thread evm
[kernel][sched]: destroying empty process evm
[kernel][x86]: pagefault caused by kernel write to FFFF80010046E338 (non present page)
at FFFFFFFF80076E8D
[kernel][x86]: sending SIGSEGV to user process (thread user thread)
[kernel][signal]: killing thread user thread because of unhandled signal 11
[kernel][sched]: destroying exited thread user thread
map a0000 (size 20000) -> 0x7b5000
run vm
[kernel][x86]: EXCEPTION: general protection fault at FFFFFFFF800CD593
``` I discovered more randomly happening faults, the gp fault happens only sometimes and its I am pretty sure its because `*(u64*) (xstate + 512 + 16)` is not zero like its supposed to be in a host xstate that I save before vmenter and load after vmexit (and the load specifically is where it faults)
idk how does it get to a non-zero state tho, if I add asserts it goes away too (or well at least it occurs less often so I haven't managed to get it to reproduce)
apparently its 0x400 when entering the run function before running xsave too, I have no idea where does it get changed (its zeroed initially)
and breaking after its allocated and putting a watchpoint didn't help either, it doesn't show any accesses to that location at all (and in info tlb that's the only address that I can see referring to the same physical page alongside the hhdm but the hhdm address doesn't get hit if watchpointed either)
apparently it gets modified by the vmptrld
that's certainly not the address that I give to it
actually I might know why, maybe its because I leave a temporary test vmcs current and free the backing page and then when I execute vmptrld again it writes the state of that vmcs that was stored on the cpu to memory before making the new vmcs current
I think that was it, doesn't look like the simd state gets modified anymore
and that other issue might also have been related, though some different issues remain if you launch multiple instances of the vm at the same time (likely because I don't make the vmcs current in any of the helper functions so things like writing to the vm's control registers might affect some random other active vm)
but that shouldn't be hard to fix, Ill just have to keep track of the currently active vmcs and if its different than the one the program wants to modify change it using vmptrld
I also found other safety issues with it like the owning vm wasn't really being referenced by the vcpus so if you'd have closed the vm handle and tried to run a vcpu funny things could happen (in the best case nothing and in worst the kernel using random freed memory as the ept along with potentially faulting if it can't traverse the map properly)
should be fixed now tho
btw whats the current situation with crescent suspend support
well I haven't really touched it in some time, last time it worked in qemu and its implemented for some devices like the ps2 and bochs fb
but on the laptop it didn't really properly work (or well it did likely enter some kind of state as the power light went off for like 2s but after that it lit back up with screen off)
has the fb been properly restored on some real hw using it
though well ig that doesn't really matter for the purposes of seeing if it spuriously wakes up
no but iirc it reboots after wake to verify that it worked
the last obos iso that I found in the uacpi thread doesn't display anything on the screen, it just reboots (and as far as I can see the power light stays on the whole time)
so either it suspends and resumes very short time afterwards or it triple faulted or did something else that caused a reboot
no
yet another obos triple fualt
obos doesn't run on amd, and I am yet to debug it
qwinci has an intel
11gen
i5 1135g7
I can also try it on my desktop rq now that I have it on an usb, brb
I'll post the latest obos iso
just let me remove the userspace stuff from the initrd to make it smaller
wait nvm dont use that
uacpi causes it to hang or smth
somewhere during driver loading
wait that should actually work, it's using uacpi master
@molten wyvern use that iso
pls
if all goes well it hangs (intentionally) in the r8169 driver
after printing the mac address
Ill try, with the old iso on this desktop it just hanged with black screen and I had to force shutdown by long power press
thanks
was this test not on desktop?
no it was on my laptop
the new iso also has the same behaviour on the laptop, it just straight up reboots right after boot to it
looks like it has the same hang with no screen output on the desktop as with the old iso too
so does it hang or triple fault?
on the desktop I assume its hang because it doesn't reboot
ok
and on the laptop its likely triple fault
without output?
it has to be
a triple fault on the laptop
debug the laptop first
I'm going to add a hang somewhere
and send you an iso
Arch_KernelEntryBootstrap:
cmp rsi, 0x554c5442
je .ok ; should triple fault on failure
xor rax,rax
jmp rax ; All hope is lost.```
that's the only code that intentionally triple faults
it checks that the hyper magic passed in rsi is what it should be
one of the first things that should happen is you getting logs if all goes well, so it's in early early boot
I'm tryna send the iso but discord is being annoying
fucking hell
Ill not be able to test it right away anyway, Ill have to first play the daily overwatch match and eat something 
I am trying to think what exactly should I do, if I want to port any kind of desktop apps then I basically need xorg or I have to rewrite parts of the apps to use my custom window protocol (which also means that I can't run any binary apps like linux factorio)
unless I'd do something similar to xwayland but that sounds painful
or you can do wayland
how about wlcrescent :^)
i would not bother messing with xorg
what would that be lol
like xwayland but between wayland and the crescent meme whatever that is, instead of x and wayland
ah, ig that could work (though first of all I'd have to make the crescent windowing thing not be shit and see what exactly would it need to be able to provide such a layer)
just layer xwayland on wlcrescent 
Xwayland isnβt bad tbh
i agree
I took a closer look at the phone touchscreen that I wanted to write a driver for and apparently the i2c serial engine its connected with is literally the only one that has disabled fifo support which means that I need a driver for some annoying serial dma thing called gpi (all the other i2c serial engines that are used to connect audio amp, fm radio, nfc and vibrator support fifo)
ig it kinda makes sense considering that you get a lot of data from it but still idk why does it have to have it disabled
at least it has some things with proper public specs like the vibrator (ti drv2624), the amplifier (ti tas2563) and the fm radio (rtc6226) looks to have but its made by some chinese company called richwave that requires some kind of signup to get it and I couldn't get past that (it just generates some kind of undescriptive error)
about the nfc thing I am not sure, its compatible within the dtb is just tms,nfc and nothing comes up with that except some belgium based software company (might be that they made the driver but the chip is made by some other company)
also apparently my ps2 driver is broken somehow again at least on the other laptop that I have (I haven't really even touched it after I improved it other than changing timeouts to be in ns)
ps2 really sucks
it just hangs somewhere (I think its within the controller init or port detection stuff but Ill have to add more prints to there)
astral curse
Qwinci pushed code to astral, now he is forever cursed
lol
real
its also annoying to debug because its the lenovo laptop that I have from work that doesn't have a proper ethernet port so no pxe
I wonder if I have tested obos on it
lol
looks like it stopped hanging inside the controller init stuff after I added prints, now it instead fails in mouse init when getting the id of it (it waits for an event but that's supposed to have a timeout, idk why isn't it working)
idk if this laptop even has a ps2 connected trackpad, it might not
aml will have answers
according to it it looks like it would have
probably, all the other lenovo laptops that I have seen have had synaptics too
about the other my own laptop I don't remember, it might have elantech
btw if its a thinkpad it has a multiplexed ps/2 as well
yeah it is a t490s
is the tracknob (idk what is it called lol) accessed using that mechanism? or does it just share the input with the trackpad?
its a separate ps/2 device
it has 3
the keyboard, the nob, and synaptics
multiplexed ps/2 supports up to 4 devices
so yeah u need to enable the multiplexed mode for it to work
interesting, I guess I can take a look at that after I have hopefully figured out the other issues
its a pretty simple thing honestly
it should still function without the multiplexed mode enabled tho right?
ah
apparently the reason for the hang was that in my sched unblock function I forgot to re-queue the thread if it was sleeping previously
I think that there is some other hang that doesn't always happen while evaluating _BST too
the good thing is that sleep apparently at least somewhat works, at least it doesn't randomly wake up on its own (though it also doesn't wake on keyboard/trackpad click) and when waking it with the power button the mute led goes on but the power button keeps pulsing (and display is off) so its not completely working
and obos hangs on this laptop because bogus ioapic redirections right?
possibly
it calls finalize_gpe, which enables some gpes that have been pending, which makes the cpu hang once it recieves the irq
we know that because it doesnt hang if he doesnt install the irq handler
annoying bug ngl
yeah
also apparently this didn't actually hang forever (it just took like a minute lol), I think it might be related to the fact that the acpi worker gets moved to a different cpu
yeah looks like pinning it to the bsp makes that not happen, idk if this is a skill issue in the kernel or some kind of firmware meme nvm it didn't fix it
and for the wake at least one possible thing that could cause the waking to fail even on power button could be if the firmware boots the code in protected mode as I rely on cs relative things in it
I should probably write a different trampoline for that case because I don't think there is any easy way to make it work on both
or well ig I can just have the entry part be set to different parts of it for them as I can reuse the long mode stuff + gdt
I wanted to do kgdb so I could debug the weird stuff like the _BST taking too long to execute but now I realized that its not so easy to implement on top of a normal socket
because like I need to have access to some other thread's stuff than the thread where the kgdb socket is served
update: it happened again a couple times, I am starting to think that it might have something to do with whether its connected to ac (idk if it was connected to a charger the previous times it happened but at least when I did the testing back then it was and now it wasn't)
also I am starting to get braindamage from the intel gpu render prms, they are literally structured the worst way possible and include irrelevant stuff in between (and the fields within the structures aren't documented very good, like wtf does Vertex URB Entry Length in pairs of 128-bit vertex element units mean or how is the urb distributed between different shader threads and are you supposed to restrict the amount of threads based on how much urb space one invocation requires or how does simd8 dispatch work (I can guess that it means that one vertex shader invocation is supposed to process multiple vertices <= 8 but idk if that's what it means) 
it's the length of a vertex URB entry, as measured in pairs of 128 bit vertex element units
i.e. probably multiples of 32
actually now that you said it I think I saw somewhere mentioned that the vertex attributes always take that amount of space in there
lmfao
im missing context to understand the rest of them
what is a URB?
uniform resource buffer?
are you doing accel CBT?
its either uniform return buffer or universal return buffer, as far as I understand its basically a region of memory used to store input vertex attributes extracted from the vertex buffer to be consumed by the vertex shader (and then the vertex shader puts its outputs to there that are then fed as inputs to the pixel shader)
yes I though it would be fun but I didn't know how bad the render spec was lol
what are you working on?
trying to make a "driver" to draw an accelerated triangle on an intel gpu
its where I got the idea from
lol
I though about what I want to do with crescent some more and I think I am going to not implement any of the linux/glibc specific things (and I am going to make more options to hzlibc to disable them, shouldn't be hard as they are already in their own folders mostly) so its just going to be an unix-like but not linux-like and then I want to actually try to do the gpu shaders (+ if it goes well enough then make some kind of primitive glsl compiler, I already kinda started one that has some of the parsing done)
hopefully its not going to make porting some stuff too hard lol
are you going to work on both new and old crescent at the same time?
Ill probably just switch between them, I just want something else custom to work on too lol
interesting
a glsl compiler sounds painful
that shader isa is tough
but it would be cool if u figured it out
I ported my gameboy emulator that originally used sdl2 for video + audio to the crescent windowing system + kernel audio interface (I think it would be better with uhda than this old one that I had but I haven't yet made the api fully functional on top of uhda) 
it also revealed some issues with window redrawing that Ill have to take a look at
the issue was pretty trivial to fix as I just needed to make some adjustments to the dirty rect calculation to take into account the borders. one other thing that I noticed is that it doesn't properly work on my phone for some reason, it just displays a static snapshot of the emu window
looks like it likely has something to do with load balancing (or smp init ig), if I disable the smp bootup it works fine
apparently I forgot to add the scheduler timer callback on the other cpus (and also enable the timer on the other cpus)
so now it works, though on real hw the ap bootup sometimes gets stuck
I finally decided that its time to commit all the changes and it literally took like 4 hours to sort them to commits that hopefully compile without any changes π it was like 33 commits lol
at least I learned that you shouldn't accumulate multiple months worth of uncommitted changes like this
lol
today I started trying to implement bluetooth over usb but apparently my xhci driver is somehow broken again so that it doesn't even detect the device in qemu
so I can't really test whether any of it works until I figure out how to fix it and what is the problem with it now
after that's figured out (and assuming that the stuff that I wrote actually works) ig I can expose some bt ioctls (or well the equivalent that I have with devlink, its going to need a new btlink or whatever) to userspace so then I can start writing the rest of the billions of layers that there are on top of the core bt inside some kind of bluetooth server lol
Damn
How does Bluetooth work
idk how does the higher level stuff work yet as I have mostly just looked at the transport layer and that's basically just some command packets to the controller passed as the body of usb setup packets or data packets to other devices yeeted through an usb bulk endpoint (+ an irq in endpoint for events like command completions from the controller)
well there are also other transports it can use besides usb like sdio (which needs an sd card driver), that's how it works on eg. qcom phones afaik
interestng
it does work
I can read the bluetooth clock and it generates a cmd complete event, the problem wasn't really the xhci code but me assuming that qemu would take host usb device vendor/product as hex by default but apparently that's not the case
now ig I can try sending some inquiry packets (or well tell the controller to start sending them, you don't have to send the packets themself yourself) and see what devices there are or smth
can u explain what ur doing exactly
for which part?
in general
writing a driver for an usb bluetooth adapter
is there like a spec for it
yes
i thought it would require proprietary firmware blobs and stuff
it probably does
but works anyway?
well at least some part of it but idk if the actual stuff that sends packets over the air works
ah
at least the inquiry works, I get an event if I put my phone into pairing mode
but also idk if its possible that the fw is retained in the device from when linux loaded it initially
yeah possibly
now I can do the same clock thing from userspace https://gist.github.com/Qwinci/4538f6f46a41f9546a759a327e984992
one problem that Ill have to solve is that there is really no way to respond to hotplugs in userspace and that's also an issue with usb stuff like this even if its not really hotplugged as the usb device driver runs in a different thread that might get scheduled after other stuff
I am starting to not like this bluetooth stuff very much lol, like why does there have to be billion different things that the software must implement
first you have the acl packets that you give to the controller, then you have multiple different types of l2cap packets (depending on whether the l2cap channel is reliable or not) that you have to split/combine to/from the acl packet data + re-send if a timeout happens + other features that tcp has too, and to create an l2cap channel to a specific service on the other device you have to use a predefined l2cap channel to first query the device for the services it has using a different protocol on top