ia64/xen-unstable

changeset 3997:4e765d177de7

bitkeeper revision 1.1236.11.1 (422c8fffPd62_3ejA06WBfNou1MZyg)

Merge bk://xen.bkbits.net/xeno-unstable.bk
into bkbits.net:/repos/x/xen-ia64/xeno-unstable-ia64.bk
author xen-ia64.adm@bkbits.net
date Mon Mar 07 17:31:43 2005 +0000 (2005-03-07)
parents 59a924789d34 f6004779d1ee
children 205e127344e9 63b7523188de
files BitKeeper/etc/logging_ok xen/arch/ia64/Makefile xen/arch/ia64/privop.c xen/arch/ia64/process.c xen/arch/ia64/tools/mkbuildtree xen/arch/ia64/xenasm.S xen/arch/ia64/xenmisc.c xen/arch/ia64/xensetup.c xen/include/asm-ia64/config.h
line diff
     1.1 --- a/BitKeeper/etc/logging_ok	Sat Mar 05 11:24:12 2005 +0000
     1.2 +++ b/BitKeeper/etc/logging_ok	Mon Mar 07 17:31:43 2005 +0000
     1.3 @@ -76,4 +76,5 @@ tlh20@elite.cl.cam.ac.uk
     1.4  tlh20@labyrinth.cl.cam.ac.uk
     1.5  tw275@labyrinth.cl.cam.ac.uk
     1.6  tw275@striker.cl.cam.ac.uk
     1.7 +xen-ia64.adm@bkbits.net
     1.8  xenbk@gandalf.hpl.hp.com
     2.1 --- a/xen/arch/ia64/Makefile	Sat Mar 05 11:24:12 2005 +0000
     2.2 +++ b/xen/arch/ia64/Makefile	Mon Mar 07 17:31:43 2005 +0000
     2.3 @@ -7,6 +7,7 @@ OBJS = xensetup.o setup.o time.o irq.o i
     2.4  	machvec.o dom0_ops.o domain.o \
     2.5  	idle0_task.o pal.o hpsim.o efi.o efi_stub.o ivt.o mm_contig.o \
     2.6  	mm_bootmem.o sal.o cmdline.o mm_init.o tlb.o page_alloc.o slab.o \
     2.7 +	extable.o linuxextable.o \
     2.8  	regionreg.o entry.o unaligned.o privop.o vcpu.o \
     2.9  	irq_ia64.o irq_lsapic.o hpsim_irq.o vhpt.o xenasm.o dom_fw.o
    2.10  # perfmon.o
     3.1 --- a/xen/arch/ia64/privop.c	Sat Mar 05 11:24:12 2005 +0000
     3.2 +++ b/xen/arch/ia64/privop.c	Mon Mar 07 17:31:43 2005 +0000
     3.3 @@ -538,7 +538,8 @@ unsigned long privop_trace = 0;
     3.4  IA64FAULT
     3.5  priv_handle_op(VCPU *vcpu, REGS *regs, int privlvl)
     3.6  {
     3.7 -	IA64_BUNDLE bundle, __get_domain_bundle(UINT64);
     3.8 +	IA64_BUNDLE bundle;
     3.9 +	IA64_BUNDLE __get_domain_bundle(UINT64);
    3.10  	int slot;
    3.11  	IA64_SLOT_TYPE slot_type;
    3.12  	INST64 inst;
    3.13 @@ -550,19 +551,14 @@ priv_handle_op(VCPU *vcpu, REGS *regs, i
    3.14  	// make a local copy of the bundle containing the privop
    3.15  #if 1
    3.16  	bundle = __get_domain_bundle(iip);
    3.17 -	if (!bundle.i64[0] && !bundle.i64[1]) return IA64_RETRY;
    3.18 -#else
    3.19 -#ifdef AVOIDING_POSSIBLE_DOMAIN_TLB_MISS
    3.20 -	//TODO: this needs to check for faults and behave accordingly
    3.21 -	if (!vcpu_get_iip_bundle(&bundle)) return IA64_DTLB_FAULT;
    3.22 +	if (!bundle.i64[0] && !bundle.i64[1])
    3.23  #else
    3.24 -if (iip < 0x10000) {
    3.25 - printf("priv_handle_op: unlikely iip=%p,b0=%p\n",iip,regs->b0);
    3.26 - dummy();
    3.27 -}
    3.28 -        bundle = *(IA64_BUNDLE *)iip;
    3.29 +	if (__copy_from_user(&bundle,iip,sizeof(bundle)))
    3.30  #endif
    3.31 -#endif
    3.32 +	{
    3.33 +//printf("*** priv_handle_op: privop bundle @%p not mapped, retrying\n",iip);
    3.34 +		return IA64_RETRY;
    3.35 +	}
    3.36  #if 0
    3.37  	if (iip==0xa000000100001820) {
    3.38  		static int firstpagefault = 1;
    3.39 @@ -783,10 +779,12 @@ char *cr_str[128] = {
    3.40    RS,RS,RS,RS,RS,RS,RS,RS
    3.41  };
    3.42  
    3.43 -void dump_privop_counts(void)
    3.44 +// FIXME: should use snprintf to ensure no buffer overflow
    3.45 +int dump_privop_counts(char *buf)
    3.46  {
    3.47  	int i, j;
    3.48  	UINT64 sum = 0;
    3.49 +	char *s = buf;
    3.50  
    3.51  	// this is ugly and should probably produce sorted output
    3.52  	// but it will have to do for now
    3.53 @@ -795,63 +793,64 @@ void dump_privop_counts(void)
    3.54  	sum += privcnt.rfi; sum += privcnt.bsw0;
    3.55  	sum += privcnt.bsw1; sum += privcnt.cover;
    3.56  	for (i=0; i < 64; i++) sum += privcnt.Mpriv_cnt[i];
    3.57 -	printf("Privop statistics: (Total privops: %ld)\r\n",sum);
    3.58 +	s += sprintf(s,"Privop statistics: (Total privops: %ld)\r\n",sum);
    3.59  	if (privcnt.mov_to_ar_imm)
    3.60 -		printf("%10d  %s [%d%%]\r\n", privcnt.mov_to_ar_imm,
    3.61 +		s += sprintf(s,"%10d  %s [%d%%]\r\n", privcnt.mov_to_ar_imm,
    3.62  			"mov_to_ar_imm", (privcnt.mov_to_ar_imm*100L)/sum);
    3.63  	if (privcnt.mov_to_ar_reg)
    3.64 -		printf("%10d  %s [%d%%]\r\n", privcnt.mov_to_ar_reg,
    3.65 +		s += sprintf(s,"%10d  %s [%d%%]\r\n", privcnt.mov_to_ar_reg,
    3.66  			"mov_to_ar_reg", (privcnt.mov_to_ar_reg*100L)/sum);
    3.67  	if (privcnt.ssm)
    3.68 -		printf("%10d  %s [%d%%]\r\n", privcnt.ssm,
    3.69 +		s += sprintf(s,"%10d  %s [%d%%]\r\n", privcnt.ssm,
    3.70  			"ssm", (privcnt.ssm*100L)/sum);
    3.71  	if (privcnt.rsm)
    3.72 -		printf("%10d  %s [%d%%]\r\n", privcnt.rsm,
    3.73 +		s += sprintf(s,"%10d  %s [%d%%]\r\n", privcnt.rsm,
    3.74  			"rsm", (privcnt.rsm*100L)/sum);
    3.75  	if (privcnt.rfi)
    3.76 -		printf("%10d  %s [%d%%]\r\n", privcnt.rfi,
    3.77 +		s += sprintf(s,"%10d  %s [%d%%]\r\n", privcnt.rfi,
    3.78  			"rfi", (privcnt.rfi*100L)/sum);
    3.79  	if (privcnt.bsw0)
    3.80 -		printf("%10d  %s [%d%%]\r\n", privcnt.bsw0,
    3.81 +		s += sprintf(s,"%10d  %s [%d%%]\r\n", privcnt.bsw0,
    3.82  			"bsw0", (privcnt.bsw0*100L)/sum);
    3.83  	if (privcnt.bsw1)
    3.84 -		printf("%10d  %s [%d%%]\r\n", privcnt.bsw1,
    3.85 +		s += sprintf(s,"%10d  %s [%d%%]\r\n", privcnt.bsw1,
    3.86  			"bsw1", (privcnt.bsw1*100L)/sum);
    3.87  	if (privcnt.cover)
    3.88 -		printf("%10d  %s [%d%%]\r\n", privcnt.cover,
    3.89 +		s += sprintf(s,"%10d  %s [%d%%]\r\n", privcnt.cover,
    3.90  			"cover", (privcnt.cover*100L)/sum);
    3.91  	for (i=0; i < 64; i++) if (privcnt.Mpriv_cnt[i]) {
    3.92 -		if (!Mpriv_str[i]) printf("PRIVSTRING NULL!!\r\n");
    3.93 -		else printf("%10d  %s [%d%%]\r\n", privcnt.Mpriv_cnt[i],
    3.94 +		if (!Mpriv_str[i]) s += sprintf(s,"PRIVSTRING NULL!!\r\n");
    3.95 +		else s += sprintf(s,"%10d  %s [%d%%]\r\n", privcnt.Mpriv_cnt[i],
    3.96  			Mpriv_str[i], (privcnt.Mpriv_cnt[i]*100L)/sum);
    3.97  		if (i == 0x24) { // mov from CR
    3.98 -			printf("            [");
    3.99 +			s += sprintf(s,"            [");
   3.100  			for (j=0; j < 128; j++) if (from_cr_cnt[j]) {
   3.101  				if (!cr_str[j])
   3.102 -					printf("PRIVSTRING NULL!!\r\n");
   3.103 -				printf("%s(%d),",cr_str[j],from_cr_cnt[j]);
   3.104 +					s += sprintf(s,"PRIVSTRING NULL!!\r\n");
   3.105 +				s += sprintf(s,"%s(%d),",cr_str[j],from_cr_cnt[j]);
   3.106  			}
   3.107 -			printf("]\r\n");
   3.108 +			s += sprintf(s,"]\r\n");
   3.109  		}
   3.110  		else if (i == 0x2c) { // mov to CR
   3.111 -			printf("            [");
   3.112 +			s += sprintf(s,"            [");
   3.113  			for (j=0; j < 128; j++) if (to_cr_cnt[j]) {
   3.114  				if (!cr_str[j])
   3.115 -					printf("PRIVSTRING NULL!!\r\n");
   3.116 -				printf("%s(%d),",cr_str[j],to_cr_cnt[j]);
   3.117 +					s += sprintf(s,"PRIVSTRING NULL!!\r\n");
   3.118 +				s += sprintf(s,"%s(%d),",cr_str[j],to_cr_cnt[j]);
   3.119  			}
   3.120 -			printf("]\r\n");
   3.121 +			s += sprintf(s,"]\r\n");
   3.122  		}
   3.123  	}
   3.124 +	return s - buf;
   3.125  }
   3.126  
   3.127 -void zero_privop_counts(void)
   3.128 +int zero_privop_counts(char *buf)
   3.129  {
   3.130  	int i, j;
   3.131 +	char *s = buf;
   3.132  
   3.133  	// this is ugly and should probably produce sorted output
   3.134  	// but it will have to do for now
   3.135 -	printf("Zeroing privop statistics\r\n");
   3.136  	privcnt.mov_to_ar_imm = 0; privcnt.mov_to_ar_reg = 0;
   3.137  	privcnt.ssm = 0; privcnt.rsm = 0;
   3.138  	privcnt.rfi = 0; privcnt.bsw0 = 0;
   3.139 @@ -859,4 +858,27 @@ void zero_privop_counts(void)
   3.140  	for (i=0; i < 64; i++) privcnt.Mpriv_cnt[i] = 0;
   3.141  	for (j=0; j < 128; j++) from_cr_cnt[j] = 0;
   3.142  	for (j=0; j < 128; j++) to_cr_cnt[j] = 0;
   3.143 +	s += sprintf(s,"All privop statistics zeroed\r\n");
   3.144 +	return s - buf;
   3.145  }
   3.146 +
   3.147 +#define TMPBUFLEN 8*1024
   3.148 +int dump_privop_counts_to_user(char __user *ubuf, int len)
   3.149 +{
   3.150 +	char buf[TMPBUFLEN];
   3.151 +	int n = dump_privop_counts(buf);
   3.152 +
   3.153 +	if (len < TMPBUFLEN) return -1;
   3.154 +	if (__copy_to_user(ubuf,buf,n)) return -1;
   3.155 +	return n;
   3.156 +}
   3.157 +
   3.158 +int zero_privop_counts_to_user(char __user *ubuf, int len)
   3.159 +{
   3.160 +	char buf[TMPBUFLEN];
   3.161 +	int n = zero_privop_counts(buf);
   3.162 +
   3.163 +	if (len < TMPBUFLEN) return -1;
   3.164 +	if (__copy_to_user(ubuf,buf,n)) return -1;
   3.165 +	return n;
   3.166 +}
     4.1 --- a/xen/arch/ia64/process.c	Sat Mar 05 11:24:12 2005 +0000
     4.2 +++ b/xen/arch/ia64/process.c	Mon Mar 07 17:31:43 2005 +0000
     4.3 @@ -242,7 +242,9 @@ void xen_handle_domain_access(unsigned l
     4.4  	unsigned long pteval, mpaddr;
     4.5  	unsigned long lookup_domain_mpa(struct domain *,unsigned long);
     4.6  	IA64FAULT fault;
     4.7 +#ifndef USER_ACCESS
     4.8  	extern void __get_domain_bundle(void);
     4.9 +#endif
    4.10  
    4.11  // NEED TO HANDLE THREE CASES:
    4.12  // 1) domain is in metaphysical mode
    4.13 @@ -265,20 +267,41 @@ void xen_handle_domain_access(unsigned l
    4.14  		vcpu_itc_no_srlz(ed,2,address,pteval,PAGE_SHIFT);
    4.15  		return;
    4.16  	}
    4.17 -if (address < 0x4000) printf("WARNING: page_fault @%p, iip=%p\n",address,iip);
    4.18 +#ifndef USER_ACCESS
    4.19  	if (*(unsigned long *)__get_domain_bundle != iip) {
    4.20  		printf("Bad user space access @%p ",address);
    4.21  		printf("iip=%p, ipsr=%p, b0=%p\n",iip,psr,regs->b0);
    4.22  		while(1);
    4.23  	}
    4.24 +#endif
    4.25 +if (address < 0x4000) printf("WARNING: page_fault @%p, iip=%p\n",address,iip);
    4.26  		
    4.27  	fault = vcpu_tpa(ed,address,&mpaddr);
    4.28  	if (fault != IA64_NO_FAULT) {
    4.29 +#ifndef USER_ACCESS
    4.30  		// this is hardcoded to handle __get_domain_bundle only
    4.31  		regs->r8 = 0; regs->r9 = 0;
    4.32  		regs->cr_iip += 0x20;
    4.33  		//regs->cr_iip |= (2UL << IA64_PSR_RI_BIT);
    4.34  		return;
    4.35 +#else /* USER_ACCESS */
    4.36 +		static int uacnt = 0;
    4.37 +		// can't translate it, just fail (poor man's exception)
    4.38 +		// which results in retrying execution
    4.39 +//printk("*** xen_handle_domain_access: poor man's exception cnt=%i iip=%p, addr=%p...\n",uacnt++,iip,address);
    4.40 +		if (ia64_done_with_exception(regs)) {
    4.41 +//if (!(uacnt++ & 0x3ff)) printk("*** xen_handle_domain_access: successfully handled cnt=%d iip=%p, addr=%p...\n",uacnt,iip,address);
    4.42 +			return;
    4.43 +		}
    4.44 +		else {
    4.45 +			// should never happen.  If it does, region 0 addr may
    4.46 +			// indicate a bad xen pointer
    4.47 +			printk("*** xen_handle_domain_access: exception table"
    4.48 +                               " lookup failed, iip=%p, addr=%p, spinning...\n",
    4.49 +				iip,address);
    4.50 +			while(1);
    4.51 +		}
    4.52 +#endif /* USER_ACCESS */
    4.53  	}
    4.54  	if (d == dom0) {
    4.55  		if (mpaddr < dom0_start || mpaddr >= dom0_start + dom0_size) {
    4.56 @@ -286,6 +309,7 @@ if (address < 0x4000) printf("WARNING: p
    4.57  			tdpfoo();
    4.58  		}
    4.59  	}
    4.60 +//printk("*** xen_handle_domain_access: tpa resolved miss @%p...\n",address);
    4.61  	pteval = lookup_domain_mpa(d,mpaddr);
    4.62  	// would be nice to have a counter here
    4.63  	//printf("Handling privop data TLB miss\n");
    4.64 @@ -755,6 +779,16 @@ ia64_handle_break (unsigned long ifa, st
    4.65  			// FIXME: need fixes in efi.h from 2.6.9
    4.66  			regs->r8 = EFI_UNSUPPORTED;
    4.67  			break;
    4.68 +		    case 0xffff: // test dummy hypercall
    4.69 +			regs->r8 = dump_privop_counts_to_user(
    4.70 +				vcpu_get_gr(ed,32),
    4.71 +				vcpu_get_gr(ed,33));
    4.72 +			break;
    4.73 +		    case 0xfffe: // test dummy hypercall
    4.74 +			regs->r8 = zero_privop_counts_to_user(
    4.75 +				vcpu_get_gr(ed,32),
    4.76 +				vcpu_get_gr(ed,33));
    4.77 +			break;
    4.78  		}
    4.79  		vcpu_increment_iip(current);
    4.80  	}
    4.81 @@ -809,6 +843,9 @@ ia64_handle_reflection (unsigned long if
    4.82  	    case 10:
    4.83  		check_lazy_cover = 1;
    4.84  		vector = IA64_DATA_ACCESS_BIT_VECTOR; break;
    4.85 +	    case 20:
    4.86 +		check_lazy_cover = 1;
    4.87 +		vector = IA64_PAGE_NOT_PRESENT_VECTOR; break;
    4.88  	    case 22:
    4.89  		vector = IA64_INST_ACCESS_RIGHTS_VECTOR; break;
    4.90  	    case 23:
     5.1 --- a/xen/arch/ia64/tools/mkbuildtree	Sat Mar 05 11:24:12 2005 +0000
     5.2 +++ b/xen/arch/ia64/tools/mkbuildtree	Mon Mar 07 17:31:43 2005 +0000
     5.3 @@ -98,6 +98,9 @@ cp_patch mm/bootmem.c arch/ia64/mm_bootm
     5.4  cp_patch mm/page_alloc.c arch/ia64/page_alloc.c page_alloc.c
     5.5  cp_patch mm/slab.c arch/ia64/slab.c slab.c
     5.6  
     5.7 +# following renamed to avoid conflict
     5.8 +softlink kernel/extable.c arch/ia64/linuxextable.c
     5.9 +
    5.10  cp_patch arch/ia64/mm/contig.c arch/ia64/mm_contig.c mm_contig.c
    5.11  cp_patch arch/ia64/mm/tlb.c arch/ia64/tlb.c tlb.c
    5.12  
    5.13 @@ -108,6 +111,7 @@ softlink arch/ia64/kernel/entry.h arch/i
    5.14  softlink arch/ia64/kernel/ia64_ksyms.c arch/ia64/ia64_ksyms.c
    5.15  softlink arch/ia64/kernel/irq_lsapic.c arch/ia64/irq_lsapic.c
    5.16  softlink arch/ia64/kernel/machvec.c arch/ia64/machvec.c
    5.17 +softlink arch/ia64/mm/extable.c arch/ia64/extable.c
    5.18  softlink arch/ia64/kernel/pal.S arch/ia64/pal.S
    5.19  softlink arch/ia64/kernel/patch.c arch/ia64/patch.c
    5.20  softlink arch/ia64/kernel/sal.c arch/ia64/sal.c
    5.21 @@ -182,6 +186,7 @@ null include/asm-ia64/domain_page.h
    5.22  null include/asm-ia64/flushtlb.h
    5.23  null include/asm-ia64/io_apic.h
    5.24  null include/asm-ia64/pdb.h
    5.25 +null include/asm-ia64/module.h
    5.26  
    5.27  softlink include/asm-ia64/acpi.h include/asm-ia64/acpi.h
    5.28  softlink include/asm-ia64/asmmacro.h include/asm-ia64/asmmacro.h
     6.1 --- a/xen/arch/ia64/xenasm.S	Sat Mar 05 11:24:12 2005 +0000
     6.2 +++ b/xen/arch/ia64/xenasm.S	Mon Mar 07 17:31:43 2005 +0000
     6.3 @@ -261,6 +261,8 @@ GLOBAL_ENTRY(ia64_prepare_handle_reflect
     6.4  	br.cond.sptk.many rp			// goes to ia64_leave_kernel
     6.5  END(ia64_prepare_handle_reflection)
     6.6  
     6.7 +#ifndef USER_ACCESS
     6.8 +// REMOVE: replaced with get_user
     6.9  // NOTE: instruction spacing must be explicit for recovery on miss
    6.10  GLOBAL_ENTRY(__get_domain_bundle)
    6.11  	ld8 r8=[r32],8
    6.12 @@ -276,6 +278,23 @@ GLOBAL_ENTRY(__get_domain_bundle)
    6.13  	nop 0
    6.14  	;;
    6.15  END(__get_domain_bundle)
    6.16 +#else
    6.17 +GLOBAL_ENTRY(__get_domain_bundle)
    6.18 +	EX(.failure_in_get_bundle,ld8 r8=[r32],8)
    6.19 +	;;
    6.20 +	EX(.failure_in_get_bundle,ld8 r9=[r32])
    6.21 +	;;
    6.22 +	br.ret.sptk.many rp
    6.23 +	;;
    6.24 +.failure_in_get_bundle:
    6.25 +	mov r8=0
    6.26 +	;;
    6.27 +	mov r9=0
    6.28 +	;;
    6.29 +	br.ret.sptk.many rp
    6.30 +	;;
    6.31 +END(__get_domain_bundle)
    6.32 +#endif
    6.33  
    6.34  GLOBAL_ENTRY(dorfirfi)
    6.35  #define SI_CR_IIP_OFFSET 0x10
     7.1 --- a/xen/arch/ia64/xenmisc.c	Sat Mar 05 11:24:12 2005 +0000
     7.2 +++ b/xen/arch/ia64/xenmisc.c	Mon Mar 07 17:31:43 2005 +0000
     7.3 @@ -216,3 +216,15 @@ physdev_pci_access_modify(domid_t id, in
     7.4  {
     7.5  	return -EINVAL;
     7.6  }
     7.7 +
     7.8 +// accomodate linux extable.c
     7.9 +//const struct exception_table_entry *
    7.10 +void *search_module_extables(unsigned long addr)
    7.11 +{
    7.12 +	return NULL;
    7.13 +}
    7.14 +
    7.15 +void *module_text_address(unsigned long addr)
    7.16 +{
    7.17 +	return NULL;
    7.18 +}
     8.1 --- a/xen/arch/ia64/xensetup.c	Sat Mar 05 11:24:12 2005 +0000
     8.2 +++ b/xen/arch/ia64/xensetup.c	Mon Mar 07 17:31:43 2005 +0000
     8.3 @@ -288,6 +288,8 @@ printk("About to call ac_timer_init()\n"
     8.4  // init_xen_time(); ???
     8.5  // schedulers_start(); ???
     8.6  // do_initcalls(); ???
     8.7 +printk("About to call sort_main_extable()\n");
     8.8 +    sort_main_extable();
     8.9  #else
    8.10      start_of_day();
    8.11  
     9.1 --- a/xen/include/asm-ia64/config.h	Sat Mar 05 11:24:12 2005 +0000
     9.2 +++ b/xen/include/asm-ia64/config.h	Mon Mar 07 17:31:43 2005 +0000
     9.3 @@ -1,4 +1,7 @@
     9.4 +// control flags for turning on/off features under test
     9.5  #undef CLONE_DOMAIN0
     9.6 +#define USER_ACCESS
     9.7 +
     9.8  // manufactured from component pieces
     9.9  
    9.10  // defined in linux/arch/ia64/defconfig
    9.11 @@ -160,6 +163,20 @@ struct pci_bus_region {
    9.12  	unsigned long end;
    9.13  };
    9.14  
    9.15 +// from linux/include/linux/module.h
    9.16 +
    9.17 +// warning: unless search_extable is declared, the return value gets
    9.18 +// truncated to 32-bits, causing a very strange error in privop handling
    9.19 +struct exception_table_entry;
    9.20 +
    9.21 +const struct exception_table_entry *
    9.22 +search_extable(const struct exception_table_entry *first,
    9.23 +	       const struct exception_table_entry *last,
    9.24 +	       unsigned long value);
    9.25 +void sort_extable(struct exception_table_entry *start,
    9.26 +		  struct exception_table_entry *finish);
    9.27 +void sort_main_extable(void);
    9.28 +
    9.29  // defined (why?) in include/asm-i386/processor.h
    9.30  // used in common/physdev.c
    9.31  #define IO_BITMAP_SIZE 32