Skip to contentSkip to conversation

x86: Optional segment type and limit checks

RFC PATCH New Jan Kiszka 5 participants 13 messages Jul 9, 2008 – Jul 16, 2008

lore
Share & tools
lore

Jan Kiszka

author
#0 lore raw

RFC PATCH 1/1 x86: Optional segment type and limit checks

As announced earlier, I developed an add-on feature for x86 emulation to support segment type and limit checks. Now I finally completed porting it over to latest SVN and added (hopefully) all the cases that were missing so far (as the customer didn't need them).

The idea of this patch is to generate calls to a check helper only in case the user requested this support via "-seg-checks". This feature remains off by default as most x86 OSes do not care about protection via segmentation anymore (and it was even removed from 64-bit modes by the CPU vendors). Moreover, checking the segment type and limit on every memory access is nothing that makes QEMU faster, so you will only want this if you are looking for very accurate emulation.

The attached patch passed our own test cases, and it boots standard Linux into X, both scenarios with -seg-checks enabled. However, though things have been checked twice, I wouldn't be surprised if there are a few typos or other errors in the check instrumentations. But at least, those won't have any impact on the disabled, standard case.

---
 target-i386/cpu.h       |    8 
 target-i386/helper.h    |    5 
 target-i386/op_helper.c |   59 ++++++
 target-i386/translate.c |  409 +++++++++++++++++++++++++++++++++++++++---------
 vl.c                    |    7 
 5 files changed, 417 insertions(+), 71 deletions(-)
target-i386/cpu.h +8 -0
Index: b/target-i386/cpu.h
===================================================================
@@ -94,6 +94,10 @@
 
 #define DESC_TSS_BUSY_MASK (1 << 9)
 
+/* flags for segment access checks */
+#define ACC_READ        0x0000
+#define ACC_WRITE       0x0100
+
 /* eflags masks */
 #define CC_C   	0x0001
 #define CC_P 	0x0004
@@ -751,6 +755,10 @@ static inline void cpu_clone_regs(CPUSta
         env->regs[R_ESP] = newsp;
     env->regs[R_EAX] = 0;
 }
+
+#define seg_checks 0
+#else
+extern int seg_checks;
 #endif
 
 #define CPU_PC_FROM_TB(env, tb) env->eip = tb->pc - tb->cs_base
target-i386/translate.c +338 -71

1,094 lines not on this page · raw message

vl.c +7 -0
Index: b/vl.c
===================================================================
@@ -198,6 +198,7 @@ CharDriverState *serial_hds[MAX_SERIAL_P
 CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
 #ifdef TARGET_I386
 int win2k_install_hack = 0;
+int seg_checks = 0;
 #endif
 int usb_enabled = 0;
 static VLANState *first_vlan;
@@ -7434,6 +7435,7 @@ static void help(int exitcode)
            "-std-vga        simulate a standard VGA card with VESA Bochs Extensions\n"
            "                (default is CL-GD5446 PCI VGA)\n"
            "-no-acpi        disable ACPI\n"
+           "-seg-checks     enable runtime segment access checks\n"
 #endif
 #ifdef CONFIG_CURSES
            "-curses         use a curses/ncurses interface instead of SDL\n"
@@ -7495,6 +7497,7 @@ enum {
     QEMU_OPTION_snapshot,
 #ifdef TARGET_I386
     QEMU_OPTION_no_fd_bootchk,
+    QEMU_OPTION_seg_checks,
 #endif
     QEMU_OPTION_m,
     QEMU_OPTION_nographic,
@@ -7588,6 +7591,7 @@ const QEMUOption qemu_options[] = {
     { "snapshot", 0, QEMU_OPTION_snapshot },
 #ifdef TARGET_I386
     { "no-fd-bootchk", 0, QEMU_OPTION_no_fd_bootchk },
+    { "seg-checks", 0, QEMU_OPTION_seg_checks },
 #endif
     { "m", HAS_ARG, QEMU_OPTION_m },
     { "nographic", 0, QEMU_OPTION_nographic },
@@ -8383,6 +8387,9 @@ int main(int argc, char **argv)
             case QEMU_OPTION_kernel_kqemu:
                 kqemu_allowed = 2;
                 break;
+            case QEMU_OPTION_seg_checks:
+                seg_checks = 1;
+                break;
 #endif
             case QEMU_OPTION_usb:
                 usb_enabled = 1;
target-i386/helper.h +5 -0
Index: b/target-i386/helper.h
===================================================================
@@ -218,4 +218,9 @@ DEF_HELPER(target_ulong, helper_rclq, (t
 DEF_HELPER(target_ulong, helper_rcrq, (target_ulong t0, target_ulong t1))
 #endif
 
+DEF_HELPER(void, helper_check_segmented_access, (target_ulong a0,
+                         int seg_reg, int type))
+DEF_HELPER(void, helper_check_segmented_access_size, (target_ulong a0,
+                         int seg_reg, int type, int size))
+
 #undef DEF_HELPER
target-i386/op_helper.c +59 -0

65 lines not on this page · raw message

author
#1 lore raw

RFC PATCH 1/1 x86: Optional segment type and limit checks - v2

This is the second version of my segment type and register check. It reduces the impact on the translator code significantly, and it also fixes a bug of the "size" helper variant in the previous version.

The idea of this patch is to generate calls to a check helper only in case the user requested this support via "-seg-checks". This feature remains off by default as most x86 OSes do not care about protection via segmentation anymore (and it was even removed from 64-bit modes by the CPU vendors). Moreover, checking the segment type and limit on every memory access is nothing that makes QEMU faster, so you will only want this if you are looking for very accurate emulation.

On Fabrice's request I tried to find the conditions which allow enabling -seg-checks by default but kicking it out most of the time during code translation. That works for 64-bit mode, of course, but I still see no clear indication for the case that 32-bit guests are not interested in type checking specifically. If you see one, let me know.

---
 target-i386/cpu.h       |    8 +
 target-i386/helper.h    |    3 
 target-i386/op_helper.c |   50 ++++++++
 target-i386/translate.c |  299 ++++++++++++++++++++++++++++++++++++------------
 vl.c                    |    7 +
 5 files changed, 296 insertions(+), 71 deletions(-)
target-i386/cpu.h +8 -0
Index: b/target-i386/cpu.h
===================================================================
@@ -94,6 +94,10 @@
 
 #define DESC_TSS_BUSY_MASK (1 << 9)
 
+/* flags for segment access checks */
+#define ACC_READ        0x0000
+#define ACC_WRITE       0x0100
+
 /* eflags masks */
 #define CC_C   	0x0001
 #define CC_P 	0x0004
@@ -751,6 +755,10 @@ static inline void cpu_clone_regs(CPUSta
         env->regs[R_ESP] = newsp;
     env->regs[R_EAX] = 0;
 }
+
+#define seg_checks 0
+#else
+extern int seg_checks;
 #endif
 
 #define CPU_PC_FROM_TB(env, tb) env->eip = tb->pc - tb->cs_base
target-i386/translate.c +228 -71

984 lines not on this page · raw message

vl.c +7 -0
Index: b/vl.c
===================================================================
@@ -198,6 +198,7 @@ CharDriverState *serial_hds[MAX_SERIAL_P
 CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
 #ifdef TARGET_I386
 int win2k_install_hack = 0;
+int seg_checks = 0;
 #endif
 int usb_enabled = 0;
 static VLANState *first_vlan;
@@ -7434,6 +7435,7 @@ static void help(int exitcode)
            "-std-vga        simulate a standard VGA card with VESA Bochs Extensions\n"
            "                (default is CL-GD5446 PCI VGA)\n"
            "-no-acpi        disable ACPI\n"
+           "-seg-checks     enable runtime segment access checks\n"
 #endif
 #ifdef CONFIG_CURSES
            "-curses         use a curses/ncurses interface instead of SDL\n"
@@ -7495,6 +7497,7 @@ enum {
     QEMU_OPTION_snapshot,
 #ifdef TARGET_I386
     QEMU_OPTION_no_fd_bootchk,
+    QEMU_OPTION_seg_checks,
 #endif
     QEMU_OPTION_m,
     QEMU_OPTION_nographic,
@@ -7588,6 +7591,7 @@ const QEMUOption qemu_options[] = {
     { "snapshot", 0, QEMU_OPTION_snapshot },
 #ifdef TARGET_I386
     { "no-fd-bootchk", 0, QEMU_OPTION_no_fd_bootchk },
+    { "seg-checks", 0, QEMU_OPTION_seg_checks },
 #endif
     { "m", HAS_ARG, QEMU_OPTION_m },
     { "nographic", 0, QEMU_OPTION_nographic },
@@ -8383,6 +8387,9 @@ int main(int argc, char **argv)
             case QEMU_OPTION_kernel_kqemu:
                 kqemu_allowed = 2;
                 break;
+            case QEMU_OPTION_seg_checks:
+                seg_checks = 1;
+                break;
 #endif
             case QEMU_OPTION_usb:
                 usb_enabled = 1;
target-i386/helper.h +3 -0
Index: b/target-i386/helper.h
===================================================================
@@ -218,4 +218,7 @@ DEF_HELPER(target_ulong, helper_rclq, (t
 DEF_HELPER(target_ulong, helper_rcrq, (target_ulong t0, target_ulong t1))
 #endif
 
+DEF_HELPER(void, helper_check_segmented_access, (target_ulong a0,
+                         int seg_reg, int type, int size))
+
 #undef DEF_HELPER
target-i386/op_helper.c +50 -0

56 lines not on this page · raw message

#2 lore raw

Re: [Qemu-devel] [RFC][PATCH] x86: Optional segment type and limit checks - v2

Quoted 12 lines · Jan Kiszka

This is the second version of my segment type and register check. It reduces the impact on the translator code significantly, and it also fixes a bug of the "size" helper variant in the previous version.

The idea of this patch is to generate calls to a check helper only in case the user requested this support via "-seg-checks". This feature remains off by default as most x86 OSes do not care about protection via segmentation anymore (and it was even removed from 64-bit modes by the CPU vendors). Moreover, checking the segment type and limit on every memory access is nothing that makes QEMU faster, so you will only want this if you are looking for very accurate emulation.

Quoted 5 lines

On Fabrice's request I tried to find the conditions which allow enabling -seg-checks by default but kicking it out most of the time during code translation. That works for 64-bit mode, of course, but I still see no clear indication for the case that 32-bit guests are not interested in type checking specifically. If you see one, let me know.

Some 32-bit guests effectively disable segment range calculations checks by setting the maximum limit and zero offset. Apparently, this is faster on some real CPUs too.

Could type checking be done at translation time, including the segment types in the translation cache key?

For guests like older Linux, with zero base and non-maximum limit in user mode, could limit checking be done by the MMU TLB instead?

-- Jamie

#3 lore raw

Re: [Qemu-devel] [RFC][PATCH] x86: Optional segment type and limit checks - v2

Quoted 6 lines

Some 32-bit guests effectively disable segment range calculations checks by setting the maximum limit and zero offset. Apparently, this is faster on some real CPUs too.

Could type checking be done at translation time, including the segment types in the translation cache key?

Maybe. If we have a spare hflags bit you could probably use that to indicate whether segment limit checks are needed.

Quoted 2 lines

For guests like older Linux, with zero base and non-maximum limit in user mode, could limit checking be done by the MMU TLB instead?

Not really. The only resonable way to do this would be to use a very large virtual address space, with the high bits being the segment descriptor. This might work for 32-bit targets on 64-bit hosts, but even then it's liable to be more pain than it's worth.

Paul

#4 lore raw

Re: [Qemu-devel] [RFC][PATCH] x86: Optional segment type and limit checks - v2

Quoted 7 lines · Paul Brook
Quoted 2 lines

For guests like older Linux, with zero base and non-maximum limit in user mode, could limit checking be done by the MMU TLB instead?

Not really. The only resonable way to do this would be to use a very large virtual address space, with the high bits being the segment descriptor. This might work for 32-bit targets on 64-bit hosts, but even then it's liable to be more pain than it's worth.

I was thinking more like this, on any host:

- All segment bases are zero, and all limits are LIMIT (3GiB for old Linux in user mode).
- When filling the MMU TLB, if it's for an address >= LIMIT, treat as MMU exception.
- Flush MMU TLB on any interesting segment change (limit gets

     smaller, etc.).

- Count rate of interesting segment changes. When it's high, switch to including segment checks in translated code (same as non-zero bases) and not flushing TLB. When it's low, don't put segment checks into translated code, and use TLB flushes on segment changes.
- Keep separate count for ring 0 and ring 3, or for "code which uses segment prefixes" vs "code which doesn't".

This would suit old Linux, as kernel code uses segment to limit copy-from/to-user range, but user code has no segment changes normally, and the user limit check is equivalent to forcing all MMU pages above that virtual address to be supervisor-only.

-- Jamie

#5 lore raw

Re: [Qemu-devel] [RFC][PATCH] x86: Optional segment type and limit checks - v2

Hi Jamie,

Quoted 9 lines · Jamie Lokier
Quoted 7 lines · Paul Brook
Quoted 2 lines

For guests like older Linux, with zero base and non-maximum limit in user mode, could limit checking be done by the MMU TLB instead?

Not really. The only resonable way to do this would be to use a very large virtual address space, with the high bits being the segment descriptor. This might work for 32-bit targets on 64-bit hosts, but even then it's liable to be more pain than it's worth.

Quoted 6 lines

I was thinking more like this, on any host:

- All segment bases are zero, and all limits are LIMIT (3GiB for old Linux in user mode).
- When filling the MMU TLB, if it's for an address >= LIMIT, treat as MMU exception.

That's interesting.

If I understand correctly, you're suggesting using segment checks in translated code if any segment has a non-zero base or a different size limit. Thus limiting the optimization to those (common) cases where the limits and bases are all the same. Presumably this would also require LIMIT to be page aligned.

One could probably allow ES, FS, and GS to have different bases/limits as long as their ranges all fit within the primary range (0..LIMIT of CS, DS, and SS). It should be okay to always emit segment checks for accesses that use these segments as they should be pretty rare.

Would this still work in 32bit flat mode?

Quoted 9 lines

- Flush MMU TLB on any interesting segment change (limit gets

     smaller, etc.).

- Count rate of interesting segment changes. When it's high, switch to including segment checks in translated code (same as non-zero bases) and not flushing TLB. When it's low, don't put segment checks into translated code, and use TLB flushes on segment changes.
- Keep separate count for ring 0 and ring 3, or for "code which uses segment prefixes" vs "code which doesn't".

Why are the heuristics needed? I wonder if the tlb flush could just be optimized.

One would only need to flush the tlb when transitioning from "segment checks in translated code" mode to "segment checks in mmu" mode, or when directly going to a new LIMIT. In these cases one could just flush NEWLIMIT..OLDLIMIT.

-Kevin

#6 lore raw

Re: [Qemu-devel] [RFC][PATCH] x86: Optional segment type and limit checks - v2

Quoted 5 lines · Kevin O'Connor
Quoted 4 lines

- All segment bases are zero, and all limits are LIMIT (3GiB for old Linux in user mode).
- When filling the MMU TLB, if it's for an address >= LIMIT, treat as MMU exception.

Quoted 7 lines

That's interesting.

If I understand correctly, you're suggesting using segment checks in translated code if any segment has a non-zero base or a different size limit. Thus limiting the optimization to those (common) cases where the limits and bases are all the same. Presumably this would also require LIMIT to be page aligned.

Yes. I hadn't thought of non-zero bases, but that would work too. Base and limit have to be page aligned. The only code where that isn't true is likely 16 bit MS-DOS and Windows code, which being designed for much slower processes, should be fine with fully inlined segment checks anyway.

Quoted 3 lines

One could probably allow ES, FS, and GS to have different bases/limits as long as their ranges all fit within the primary range (0..LIMIT of CS, DS, and SS).

You could also translate just the base offset adding, in cases where the limit covers the whole 4GiB. But that adds more translation key bits.

It's probably worth including ES as a "primary" segment like DS.

Quoted 2 lines

It should be okay to always emit segment checks for accesses that use these segments as they should be pretty rare.

In Windows, and modern Linux, %fs or %gs are used in userspace code for thread-specific variables. In older Linux kernels, %fs is used to copy data to/from userspace memory. Maybe the translated checks for these are not enough overhead to matter?

Quoted 1 line

Would this still work in 32bit flat mode?

It will if QEMU's MMU TLB is always used, and uses an identity mapping. I'm not familiar with that part of QEMU, but I had the impression it's always used as it also traps memory-mapped I/O.

In which case, it should work in 16 bit flat mode too :)

Quoted 10 lines
Quoted 9 lines

- Flush MMU TLB on any interesting segment change (limit gets

     smaller, etc.).

- Count rate of interesting segment changes. When it's high, switch to including segment checks in translated code (same as non-zero bases) and not flushing TLB. When it's low, don't put segment checks into translated code, and use TLB flushes on segment changes.
- Keep separate count for ring 0 and ring 3, or for "code which uses segment prefixes" vs "code which doesn't".

Quoted 2 lines

Why are the heuristics needed? I wonder if the tlb flush could just be optimized.

Even if TLB flush itself is fast, you need to refill the TLB entries on subsequent memory accesses. It's good to avoid TLB flushes for that reason.

I'm thinking of code like this from Linux which does

movl %fs:(%eax),%ebx
movl %ebx,(%ecx)

I.e. rapidly switching between segments with different limits, and the %ds accesses are to addresses forbidden by %fs. If you're inlining %fs segment checks, though, then no TLB flush will be needed.

Quoted 4 lines

One would only need to flush the tlb when transitioning from "segment checks in translated code" mode to "segment checks in mmu" mode, or when directly going to a new LIMIT. In these cases one could just flush NEWLIMIT..OLDLIMIT.

That's true, you could optimise the flush in other ways too, such as when changing protection ring, just flush certain types of TLB entry. Or even keep multiple TLBs on the go, hashed on mostly-constant values like the translation cache, and the TLB choice being a translation cache key so it can be inlined into translated code. I didn't want to overcomplicate the suggestion, but you seem to like funky optimisations :-)

-- Jamie

author
#7 lore raw

[Qemu-devel] Re: [RFC][PATCH] x86: Optional segment type and limit checks - v2

Quoted 75 lines · Jamie Lokier
Quoted 11 lines · Kevin O'Connor
Quoted 4 lines

- All segment bases are zero, and all limits are LIMIT (3GiB for old Linux in user mode).
- When filling the MMU TLB, if it's for an address >= LIMIT, treat as MMU exception.

That's interesting.

If I understand correctly, you're suggesting using segment checks in translated code if any segment has a non-zero base or a different size limit. Thus limiting the optimization to those (common) cases where the limits and bases are all the same. Presumably this would also require LIMIT to be page aligned.

Yes. I hadn't thought of non-zero bases, but that would work too. Base and limit have to be page aligned. The only code where that isn't true is likely 16 bit MS-DOS and Windows code, which being designed for much slower processes, should be fine with fully inlined segment checks anyway.

Quoted 3 lines

One could probably allow ES, FS, and GS to have different bases/limits as long as their ranges all fit within the primary range (0..LIMIT of CS, DS, and SS).

You could also translate just the base offset adding, in cases where the limit covers the whole 4GiB. But that adds more translation key bits.

It's probably worth including ES as a "primary" segment like DS.

Quoted 2 lines

It should be okay to always emit segment checks for accesses that use these segments as they should be pretty rare.

In Windows, and modern Linux, %fs or %gs are used in userspace code for thread-specific variables. In older Linux kernels, %fs is used to copy data to/from userspace memory. Maybe the translated checks for these are not enough overhead to matter?

Quoted 1 line

Would this still work in 32bit flat mode?

It will if QEMU's MMU TLB is always used, and uses an identity mapping. I'm not familiar with that part of QEMU, but I had the impression it's always used as it also traps memory-mapped I/O.

In which case, it should work in 16 bit flat mode too :)

Quoted 11 lines
Quoted 9 lines

- Flush MMU TLB on any interesting segment change (limit gets

     smaller, etc.).

- Count rate of interesting segment changes. When it's high, switch to including segment checks in translated code (same as non-zero bases) and not flushing TLB. When it's low, don't put segment checks into translated code, and use TLB flushes on segment changes.
- Keep separate count for ring 0 and ring 3, or for "code which uses segment prefixes" vs "code which doesn't".

Why are the heuristics needed? I wonder if the tlb flush could just be optimized.

Even if TLB flush itself is fast, you need to refill the TLB entries on subsequent memory accesses. It's good to avoid TLB flushes for that reason.

I'm thinking of code like this from Linux which does

   movl %fs:(%eax),%ebx
   movl %ebx,(%ecx)

I.e. rapidly switching between segments with different limits, and the %ds accesses are to addresses forbidden by %fs. If you're inlining %fs segment checks, though, then no TLB flush will be needed.

Quoted 4 lines

One would only need to flush the tlb when transitioning from "segment checks in translated code" mode to "segment checks in mmu" mode, or when directly going to a new LIMIT. In these cases one could just flush NEWLIMIT..OLDLIMIT.

Quoted 6 lines

That's true, you could optimise the flush in other ways too, such as when changing protection ring, just flush certain types of TLB entry. Or even keep multiple TLBs on the go, hashed on mostly-constant values like the translation cache, and the TLB choice being a translation cache key so it can be inlined into translated code. I didn't want to overcomplicate the suggestion, but you seem to like funky optimisations :-)

Don't want to stop all your creativity, but just like Paul I'm also a bit skeptical about the TLB way of achieving range and type safety.

My major concern once was that the TLB works on a global scope so that you cannot tell the original segments behind some address apart. And extending the virtual address space for this is a no-go on 32-bit hosts (which I unfortunately had and still have to support here :->).

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#8 lore raw

Re: [Qemu-devel] Re: [RFC][PATCH] x86: Optional segment type and limit checks - v2

Quoted 2 lines · Jan Kiszka

Don't want to stop all your creativity, but just like Paul I'm also a bit skeptical about the TLB way of achieving range and type safety.

Sure, that's understandable. There has to be some "show me the code"
- I wish I had the time. These are not simple optimisations, but they could make segment checks free for most guests, so it's worth considering them even if they're discarded.

Quoted 2 lines

My major concern once was that the TLB works on a global scope so that you cannot tell the original segments behind some address apart.

Yes. The only way around it is context - either having multiple TLBs, or inlining segments into translated code, so you tell the original segments apart at the call site.

Quoted 3 lines

And extending the virtual address space for this is a no-go on 32-bit hosts (which I unfortunately had and still have to support here :->).

Definitely not increasing the virtual address space - I'm still using 32-bit hosts too :-) I'm not sure that would be safe even on 64-bit hosts - what if the guest has its own uses for the whole address space?

Expanding the TLB key space (or equivalently, multiple TLBs) is different from expanding the virtual address space, though.

-- Jamie

#9 lore raw

Re: [Qemu-devel] Re: [RFC][PATCH] x86: Optional segment type and limit checks - v2

In reply to Jan Kiszka

Hi Jan,

Quoted 8 lines · Jan Kiszka
Quoted 8 lines
Quoted 7 lines · Kevin O'Connor

Thus limiting the optimization to those (common) cases where the limits and bases are all the same.
One could probably allow ES, FS, and GS to have different bases/limits as long as their ranges all fit within the primary range (0..LIMIT of CS, DS, and SS).
It should be okay to always emit segment checks for accesses that use these segments as they should be pretty rare.

[...]

Quoted 5 lines

Don't want to stop all your creativity, but just like Paul I'm also a bit skeptical about the TLB way of achieving range and type safety.

My major concern once was that the TLB works on a global scope so that you cannot tell the original segments behind some address apart.

If all five segments have the same base and limit (0..LIMIT) then I would think it would not matter what segment filled a TLB. (It should not be possible to fill a TLB outside of 0..LIMIT, and any access to a tlb in 0..LIMIT should be okay regardless of the segment used.)

Of course, it's not uncommon for FS and GS to have a different base. In this case, it should still be safe as long as FS/GS don't allow access outside of 0..LIMIT (so that invalid TLBs don't get loaded) and one emits limit checks on each FS/GS use (so that the limits on FS/GS are enforced).

Qemu already has an optimization (HF_ADDSEG_MASK) for the case where DS/ES/SS all have a zero base. I was thinking that an optimization could noticeably reduce the cost of limit checks for the common case where DS/ES/SS all have a zero base and the same limit. (I incorrectly stated CS/DS/SS above.)

Of course, it would require a lot of work, and it would be hard to verify that all the corner cases were handled. So, I was more thinking out loud than proposing a solution. :-)

Quoted 3 lines

And
extending the virtual address space for this is a no-go on 32-bit hosts (which I unfortunately had and still have to support here :->).

Yeah - I wouldn't want to go there. Trying to maintain multiple TLBs or adding more bits to the TLB hash just seems silly to me.

-Kevin

#10 lore raw

Re: [Qemu-devel] Re: [RFC][PATCH] x86: Optional segment type and limit checks - v2

Quoted 9 lines · Kevin O'Connor

Qemu already has an optimization (HF_ADDSEG_MASK) for the case where DS/ES/SS all have a zero base. I was thinking that an optimization could noticeably reduce the cost of limit checks for the common case where DS/ES/SS all have a zero base and the same limit. (I incorrectly stated CS/DS/SS above.)

Of course, it would require a lot of work, and it would be hard to verify that all the corner cases were handled. So, I was more thinking out loud than proposing a solution. :-)

Just "thinking out loud" further - a simpler optimization would be to extend the existing HF_ADDSEG_MASK flag to the case where DS/ES/SS have a base a zero, a limit of 0xffffffff, and are read/writable. Then, one would only need to emit segment checks when one of the above conditions are not met or an explicit segment override to another segment is given.

This simpler optimization would miss some opportunities, but it would be much easier.

-Kevin

#11 lore raw

Re: [Qemu-devel] [RFC][PATCH] x86: Optional segment type and limit checks - v2

In reply to Jan Kiszka
Quoted 9 lines · Jan Kiszka

This is the second version of my segment type and register check. It reduces the impact on the translator code significantly, and it also fixes a bug of the "size" helper variant in the previous version.

The idea of this patch is to generate calls to a check helper only in case the user requested this support via "-seg-checks". This feature remains off by default as most x86 OSes do not care about protection via segmentation anymore (and it was even removed from 64-bit modes by the CPU vendors).

Two current users of protection via segmentation I know of

- 32-bit linux with the ExecShield capability will still use segmentation to split the address space into executable vs non-executable regions, if the CPU doesn't have NX bit support.
- 32-bit Xen uses segmentation for protecting the hypervisor.

Regards,
Daniel

Signature · 4 lines
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
author
#12 lore raw

[Qemu-devel] Re: [RFC][PATCH] x86: Optional segment type and limit checks - v2

Quoted 11 lines · Daniel P. Berrange
Quoted 9 lines · Jan Kiszka

This is the second version of my segment type and register check. It reduces the impact on the translator code significantly, and it also fixes a bug of the "size" helper variant in the previous version.

The idea of this patch is to generate calls to a check helper only in case the user requested this support via "-seg-checks". This feature remains off by default as most x86 OSes do not care about protection via segmentation anymore (and it was even removed from 64-bit modes by the CPU vendors).

Quoted 6 lines

Two current users of protection via segmentation I know of

- 32-bit linux with the ExecShield capability will still use segmentation to split the address space into executable vs non-executable regions, if the CPU doesn't have NX bit support.
- 32-bit Xen uses segmentation for protecting the hypervisor.

Ah, good to be reminded that we are not alone with our segmented OS here. ;)

That makes me realize that my patch lacks range checks for code segments. I think I left it out as it is not that trivial...

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux