gcc asm inline port in/out in x86 protected mode - Page 1
Forum section: electronics / general

author: DiTBho
author_rank: Super Contributor
timestamp: May 06, 2023, 09:03:40 pm
content: Code:static void port_out(uint16_t port,uint8_t value){asm volatile ("outb %0, %1" : : "a" (value), "Nd" (port));}static uint8_t port_in(uint16_t port){uint8_t ans;asm volatile ("inb %1, %0" : "=a" (ans) : "Nd" (port));return ans;}is this stuff correct when the x86-CPU is in protected mode?(32bit)

author: magic
author_rank: Super Contributor
timestamp: May 07, 2023, 05:17:53 am
content: Seems about right if you didn't swap the operands or something, not sure how the silly AT&T syntax works for these instructions.Of course they are still valid instructions in protected mode. Pretty sure it should work in long mode too.

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 07, 2023, 08:51:09 am
content: There are two details to consider:Protected mode privilege levelDirect access to I/O ports requires IOPL 0, as determined by bits 12 and 13 in extended flags (EFLAGS).SyntaxIn AT&T syntax (GCC or clang on x86 or x86-64 -m32), you want to usestatic inline void outb(const int port, const unsigned char value){asm volatile ( "outb %%al, %%dx":: "a" (value), "d" (port) );}static inline unsigned int inb(const int port){unsigned char value;asm volatile ( "xor %%eax, %%eax\n\t""inb %%dx, %%al": "=a" (value): "d" (port) );return value;}noting that only the low 16 bits ofportare used, and low 8 bits ofvalue. All 24 high bits of the value returned byinb()will always be zero. (This eliminates certain cases where the high bits of eax register leak through the return value, even when the return type were unsigned char.)You can omit theinlineif you wish, I only use it to remind us humans that these are an accessor/helper function (which I typically put in a header file), and not "normal" local functions.

author: DiTBho
author_rank: Super Contributor
timestamp: May 07, 2023, 10:08:13 am
content: thanks, guysI don't like x86(1) at all, but I am writing a special monitor for my Soekris net5501.So it's something that boots inreal-mode(pure assembly code) and then switches intoprotected-mode(pure assembly code but jumping into crt0, and then to C main).Code:MBR boot, CPU in 16-bit ModeCHS loading sec2-10 ... doneconsole=/serial0,115200-8-n-1Switching to 32-bit Mode ... doneInstalling ISRs ... doneEnabling external interrupts ... doneInitializing dynamic memory ... donesuppa shell> helphallo - if you see the reply, it means it's starting to workhalt - halt the CPU>the above twoin/out x86-portfunctions are needed to write the serial driver (drivers/serial.c)(1) actually it's an AMD Geode LX @ 500Mhzcompatible with x86-i586

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 07, 2023, 11:00:43 am
content: AFAIK you can use grub2 or syslinux/extlinux to boot Soekris net5501.For grub2, the LHS and CHS geometry must match, because the BIOS uses CHS for small drives and LHS for larger ones. And you may need to set some option to make sure grub does not wait forever if there is no serial (terminal) connected.In case you're not aware,thisandthisandthismay be useful.

author: magic
author_rank: Super Contributor
timestamp: May 07, 2023, 11:08:11 am
content: There are apparently some mechanism for permitting I/O port access by unprivileged tasks so it's not that simple. Wouldn't be surprised if they were used by Windows 98 to run DOS programs or the various VXD drivers.But in ring 0 you don't care.https://www.felixcloutier.com/x86/out

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 07, 2023, 11:59:32 am
content: Quote from: magic on May 07, 2023, 11:08:11 amOn other rings, thetask state segmentcan contain a pointer to a bitmap where nonzero bits allow the current task access to said port. This is not a kernel facility, it is provided by the x86 protected mode itself.This is used in for example Linux via theioperm()kernel interface; the permission/bitmap is retained over an exec. The ioperm() call itself requires either root privileges or the CAP_SYS_RAWIO capability.

author: DiTBho
author_rank: Super Contributor
timestamp: May 07, 2023, 12:23:23 pm
content: Quote from: Nominal Animal on May 07, 2023, 11:00:43 am.... on the last dumpster dive my friends found qty=6 Soekris net5501, most completely smashed as if hit by a giant heavy hammer (wtf?!? why?.?.?), some rusted and with popped caps, plus oxidation from being exposed to rain for months, but the last unit was promising: it powered up, and despite the serial port looked drunk as it outputted strings with missing or weird chars, I found it was only a pin with a floating ground connection.The mobo was cleaned, easily repaired and finally re-installed into its still rusty metal case waiting to be repainted, but it's back to working conditionYub,grubis an option, and it can be configured to reassign the console to Com1 but- I don't like it- I also need a monitor, not only a bootloader- so I want something like U-boot- I don't want to deal with PC_part- I don't want to deal with EFI_part- I need to initialize special PCI-fpga stuff (the net5501 offers a PCI 3.3V slot)- I want to tftpbootQuote from: Nominal Animal on May 07, 2023, 11:00:43 amI think I will use the BIOS disk calls (CHS) only to load the second stage, then I will implement a PCI driver to access the PATA controller in order to directly access the disk in LBA mode.And in LBA, it will load the kernel in ram, and jump into kernel_start.I already have a working skeleton- MBR: working- disk CHS: working- second stage: partially working- monitor (ram-dump, edit, fill): partially completed- micro shell: partially completed- serial console: working- dynamic ram: workingThe max size of the final code must be < 800Kbyte

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 07, 2023, 01:41:07 pm
content: Quote from: DiTBho on May 07, 2023, 12:23:23 pmI recommend having/bootbe a separate partition at the beginning of the disk. Then, as long as your CHS geometry matches the LBA mode, it'll just work.Soekris net5501 was apparently widely used with old Ubuntu and Gentoo versions, so you'll find quite a lot of information there. Furthermore, if you set up an image with an old distro that supported net5501 out of the box, you can boot it and compare /proc and /sys pseudofiles to see if your custom kernels (kernel configs) have all the necessary/useful options selected.